TRIGONOMETRY SCRIPT FOR RPG MAKER 2003

includes how to use it to make ring menus and more!

• Kazesui
• 05/27/2011 04:39 PM
• 11255 views
This tutorial will provide a rm2k3 project with some common events which you can paste into your own project and use for various purposes. The project also contains a few examples of what you can do with these trigonometric functions, like creating a ring menu.
This tutorial will explain how to use the event scripts, but will not go into great detail as to how they actually work (i.e. black magic, just accept it).
Also, this tutorial will require a minimum of intermediate level at eventing for you to be able to keep up.

The project template: http://rpgmaker.net/users/Kazesui/locker/Kazesui_Trigonometry_Scripts.zip

I will explain shortly how the trigonometric functions themself work, and I feel that the best way to do it, is with an illustration:

In a circle with radius 1000, if you have an angle rising from the x axis, the trigonometric functions will return the coordinates in x and y on the circle given the angle.
In this example, the angle is 30 degrees. with a 30 degree angle, the line generated from that will hit the circle at 866 along the x axis and 500 along the y axis.
if you multiply the radius of the circle sine of 30 degrees, i.e. 1000*sin(30) you get 500, and 1000*cos(30) will give you 866.

If we have a picture which will move instantly to coordinate x and y, and these are generated getting the sine and cosine for a angle, then increase the angle before moving the picture again, it will move around in a circle. This is one way to understand trigonometry for some uses, and it can be pretty useful

If you still don't get angles to well and stuff, you could give this little game a try: Trigonometry game

The project includes 5 common event scripts. They require the variables 101 to 160 to work properly. There are a few here and there among them which aren't being used, and some could be repositioned without too much trouble, but most likely it will be easier just to keep those variables free when using these events.

So let's look at the event scripts, the first being "CreateTrigTable".
it looks like this:

The first variable operation has a comment above it saying "Set ID of argument variable (angle)". What this means, is that the number you set that variable equal to, will be ID of the variable used as the angle for determining the value of the sine and cosine. At default, it's set to 1, meaning that you're very first variable in the list will be used unless you set it to something else.
Remember, it's the number you should change, not the variable itself.

Same deal for the next two variable operations. These signify in which variables the result should be placed. The first is which variable the cosine should be returned to, and the second which variable to sine should be returned to.
The next variable operation deals with where you want the variables containing the "lookup table" to be. it's set to be stored from variable 10000 to 10724 by default, i.e. outside the normal variable array range, so it's less likely that you have to do anything with this variable.

Once these four variables are set, you don't have to do anything more with the event. Just call it once, and then you can call the event "GetCoSinusA()" to get the trigonometric values.
Let's do an example: let's say the variable 0001 contains the value 60, and you've called upon "CreatTrigTable" with it's default values. Then variable 0002 and 0003 will now have the values 500 and 866. The trigonometric values are multiplied by 1000 to avoid the problem of having no decimal point numbers. And that's all there is to using it.

If you're fine by just knowing how to use it move on, if you want to know a bit more about it works click here:

CreateTrigTable does, as said, create a lookup table. What this means is that it stores the values of sine and cosine for all angles from 0 to 359, and the GetCoSinus converts whatever angle you used to one ranging from 0 to 359, and then does take the startID of the lookup table and add the angle as offset so that it points to variable with the correct trigonometric value, so that it can send it to the designated "return" variables.
It's done this way since doing a lookup like this is simply considerably faster than any alternative way and is sane enough when you only have 720 values to store anyway. The 4 extra variables are used for storing information from which variable it should get the angle, and where it should return the sine and cosine and the last is just 0 to signify end of info and beginning of lookup table.

And now we'll look at the 3 other scripts. Again we have a "create" event, this time for ArcTan:

And this works much in the same way as last time. First 3 variables here define from where the "arguments" should come, like the angle in "GetCoSinus".
First variable is the value you would normally put in a arctan to return the angle in degrees.
Second variable is a length in the x direction, and the third a length in the y direction.
the fourth variable is where the result should be returned to, and the fifth is where to store some information used.

Once the create has been called once, you can start use GetAngleA and GetAngleB.
GetAngleA only uses the first argument and returns a positive angle from 0 to 90.
GetAngleB uses the argument two and three and returns a positive angle from 0 to 359

I know this can be a little hard to process, if you don't already know too much about trigonometry, and the terms might be a bit difficult as well. So I will now show a few examples to demonstrate how it works and how it can be used.

This example shows how to make a simple ring menu, which rotates when you click to either side.

First off, you need to call upon CreateTrigTable to allow the usage of GetCoSinus.
Remember, it GetCoSinus won't work without CreateTrigTable having been called once, but we only need to call it a single time in the game, so it shouldn't be called more than once either.
In this example this is done by letting the upper left event called "Button Handler" being set to autostart and then calling a switch when it's done, which runs on parallel process and waits for the player to hit the cancel key.
Once that happens it sets on a switch which activates a auto-start event controlling the menu which looks a bit like this:

Hero we can see two variables RingOrigo x and y. They mark the center point of a circle in screen relative coordinates and are currently set to the middle of the screen. Next, there's a variable Radius sets how big the circle should be. The menu items will follow along the lines of the circle, so the bigger the radius, the further away from each other they will be.
the Angle variable is set to 0, so that the items will always created in the same order when the menu is opened.
After this, this event's page 1 is called:

Here we can see the "GetCoSinus" being used. It takes the current angle and returns the cosine and sine in variable 2 and 3, which are set to variables for the different menu items (through pointers) with 90 degrees between them.
After the variables have been set, they are multiplied by the radius, and then divided by 1000 since the sine and cosine are already 1000 times bigger than normal. finally x coordinates are added the x coordinate of origo, and same for y.
the angle is subtracted by 360 to return it to it's orginal value before calling this page.

Back in the page handling the flow of the menu, you can now press left or right to rotate the menu. This is done by calling page 2:

This page sets up a label loop and a variable which counts the amount of times you've looped. The angle is increased by 3 for each time, and this is something you can increase or decrease to make it spin faster or slower. You should just make sure that you scale the amounts of iteration done in the loop accordingly by adjusting the number in the branch. It then calls page 1 which gets coordinates given any spesific angle and repeats until the loop has done 30 iterations, meaning a total increase of 90 degrees.
The Rotate Left event is pretty much the same, except that it decreases the angle by -3 instead.

And that's pretty much all there is to this basic ring menu. You can inspect it more closely by looking at the project in the maker.
There you can also find a more Fancy ring menu.

This ring menu, takes it a step further and scales the sizes of the items depending on their angle, as well as it rotates in an ellipse rather than a circle.
It also grays out the other items which aren't currently selected.

All in all, most code is the same, except we now have 2 radiuses. One for the x direction and one for the y direction, with the y one being quite smaller. This creates the ellipse shape. Also instead of calling "move picture" directly, it now goes through other event pages which have quite a few branches which will trigger different move picture depending on the angle.

Stealth System

Trigonometry can also be used to create guards which look in a certain direction, but who can't see through walls. For this, we need both CreateTrigTable and CreateArcTan to have been called, so a similar event for initializing both of them like with the ring menu would be neccessary.

You're within the sight range of this guard, but since you're hiding behind a wall, he can't see you. But when you're out in the open like this:

You're spotted. So let's take a look at the code which the guard has to detect wether he sees you or not.

First, we get the screen relative coordinates of the guard. Tile based should work too, but since we need to move the picture with screen relative ones anyway, we might as well. Screen relative coordinates are more accurate as well, so wouldn't be stupid to get accustomed to using them. the -8 before the move picture is just for aesthetical reasons (as long as followed by +8 afterwards).
We then subtract the the hero coordinates from the guard coordinates (important, the object which "looks" need to be the one which gets subtracted).

Once we have the differences we store them in the variables we'll use as argument 2 and 3 for GetAngleB, but we won't call it yet. First we'll multiply the guard coordinates with themselves and add both of them into a variable and the check if it's less than the radius timed itself.
In this example a radius of 100 pixels is used, so if the difference in coordinates multiplied by themself and added into one is less than 10000, we know that the hero is in a circle of radius 100 of the guard.

We then call GetAngleB to get the angle between them and call Page 1 which does a few branches to check the angle. If the guard is facing down, then the hero is in visible range is the angle between them is between 30 and 150 degrees, if the guard has a 120 degree wide sight range.
notice that since this is on a computer the y axis is positive downwards, meaning the the angles go clockwise rather than counterclockwise.

With this, we'll know if the hero is within the normal sight range, but we still don't know if the hero is hiding between a wall or not, so to check that, we call another event page.

We now take the angle between the hero and the guard, and call on GetCoSinus to get the cosine and sine values for that angle. And we then create a label loop.
Hero we take 2 variables, x with cosine value, and y with the sine value. we multiply them by the radius then divide by 1000 to get the pixel coordinates, we add the coordinates of the guard which is the center of this circle, we then divide by 16 to get the tile coordinates and then stores the terrain ID at those coordinates. By setting the terrain ID of the tiles on the chipset we don't want the guard to be able to look through to a spesific value, we can now if there's something in the way of sight. Here we've chosen 8 as the spesific value to be checked for.

If it doesn't fit a variable SightEnd will be set to the radius and multiplied by itself, and then checked with a branch if it's bigger than "guard x" which contains the length between guard and hero calculated earlier. If not, radius is added by one and another iterations start. I it's bigger, a switch BlockedSight will be set to off, meaning there was no obstacle blocking the view of the guard.

And thus, we have a system which tells if guards can see the hero, limited by the view. Using the trigonometric scripts, you could also make a rotating camera which checks for intruders. There's lot of stuff for which you can use trigonometry, so download the project template and have fun :3

http://rpgmaker.net/users/Kazesui/locker/Kazesui_Trigonometry_Scripts.zip

Posts

Pages: first prev 123 next last
bulmabriefs144
Sexy Alphys!
2525
You mean my idea?

Well, no. Still designing it, pretty sure as designed it can't do stuff like show items as they update (without serious coding).

I just think the severe overcomplication of this concept and most people not wrapping their head around it is why there aren't more SD-style games.

I got Cs in math cuz tests made me nervous. I liked programming cuz my brain saw it as language, and I had fun figuring out how to get it to do stuff.

I like some of Kaz's ideas, but this feels too much.
Kazesui
5466
The point of this tutorial (and/or tool in form of some pre-built event scripts), was to make it possible to use trigonometric functionality to an engine which does not normally have this. I took some time to create a way to get this with the limitations imposed by the engine, so that people didn't have to spend the setup time themselves and can just straight use it.

The second part was to show a couple of examples of what you can do with trigonometric functions in games, not that these are the only solutions or even the preferred solutions.

Using trigonometry to create a ring menu is a good way to go about it, as it is quick to do (which is a reason I chose it to use it as an example), and it allows for changes easily (ring radius by changing one variable, simulation of depth by making the ring oval instead of circular. Again, that's not to say that this is the only way to do it (certainly not), and if the math is a barrier then other solutions might be better for you and others with similar problems.

In the end, trigonometry is a tool which widens the amount of ways you can tackle a challenge you want to overcome. This exact script was used in Zero Base (the Gradius like shooter I made in this engine) to send enemy bullets in the direction of the hero with a granularity of 1 degree. Being able to use arctan to figure out the angle between the player and the enemy and then figure out how to update the direction of the bullets make this a very convenient way of solving it. And this is just one of many examples where trig is a very useful tool. Maybe a bit complicated for some (in particular within the rm2k3 community), but helpful to others and hopefully even motivational to some, giving them reason to study these things harder as they see actual application of what they get taught in school
bulmabriefs144
Sexy Alphys!
2525
I guess the bottom line for me was... it's kinda reading a programming book where the writer teaches you to do complicated stuff, but you didn't realize when buying it that it was an advanced book, so you're trying to do specific processes and walk away thinking that this is the only way to do line of sight or ring menus.

I've read C++ books that were so obfuscating that it was years before I tried coding again, because it was like "welp, this is out of my reach." And yeah, for trigonometry, it's great. It's just the sort of thing where I'd like to do a follow-up showing that you don't NEED trigonometry, it just helps you make circles instead of blocked line of sight regions.
2112_kniL
7031
Nobody is forcing you to use trig. I found this very helpful and would prefer this over manually creating a system to mimic a ring menu. Besides, this can be used for more than just that one thing. I don't see the point of your comments. Do it your own way, write your own tutorial, why try to shit on this? Especially after all these years.
pianotm
The TM is for Turtle Motivator
21412
Yeah, this tutorial opened my eyes to just how fucking useful trig is to a game dev, and if you want to learn actual coding, it's actually kind of mandatory.
bulmabriefs144
Sexy Alphys!
2525
Do it your own way, write your own tutorial, why try to shit on this? Especially after all these years.

Why? Pretty much this.

author=pianotm
Yeah, this tutorial opened my eyes to just how fucking useful trig is to a game dev, and if you want to learn actual coding, it's actually kind of mandatory.

The point being that people still feel like it's mandatory for better code or something. That was why I was trashing on it.

Dude, there's art major programmers and comp science major ones.

The art major ones make a project like this using the easiest possible way (probably XY ranges for line of sight, and some some art project deal for ring menu).

Whereas if you got some kind of graphics thing and told people "you must be able to hand draw mandalas" a 3D drafter says, "no I don't" and makes the entire thing using equation.

My beef isn't with trig at all, it's a nice utility. I'm trashing one-size-fits-all mentality. The "you need this for..." thinking. Maybe you don't.

Darken
3377
bulmabriefs144
Sexy Alphys!
2525
I'm not sure the analogy fits. The analogy here is that someone bars something here then blames everyone cuz it can't possibly work any other way.

It's more like modding the wheels to be triangular.

Something where you could technically ride the bike, but it would require a person who is tremendously stubborn.

There's still a whole "why would you do this?!?" But hey, I don't criticize you people with your circular wheels. I still think you people are crazy privately though. But whatever.
Darken
3377
the analogy is that youre the one creating problems for yourself over nothing.
bulmabriefs144
Sexy Alphys!
2525

(Thinks some more)

...Nah that can't be it.
I love how forums never change

I can't fun too much, I was like this back in 2009 when I first joined. There's nothing like being an edgy college undergrad on the Internet.
bulmabriefs144
Sexy Alphys!
2525
Update: This is how I did Ring Menus

And no I didn't need no stinking trig classes that I got a C+ in.

https://rpgmaker.net/engines/rt2k3/utilities/207/

Note the almost complete lack of variables, much less trig equations.
narcodis
heaviness
3499
author=bulmabriefs144
Update: This is how I did Ring Menus

And no I didn't need no stinking trig classes that I got a C+ in.

https://rpgmaker.net/engines/rt2k3/utilities/207/

Note the almost complete lack of variables, much less trig equations.

Doesnt look like the same of ring menu. Typically a ring menu rotates around.

Of course hard coding positions is always possible. The point of using trig functions is to make the code easily extendable and reusable. What if you decide you need more menu items? Perhaps an arbitrary number of them that can change? What if you want to resize the ring? Sure, you can write code to cover each possibility, but it would sure be nice to just pass a number or two into a function call and have the code do the rest. That's all the tutorial is addressing.

But you do you!
Tw0Face
1743
Wow, I never thought of solving Event problems like that. I think this is an awesome idea and I'll definitely check this out. Especially the way your Stealth System works seems to be an huge improvement towards many other things I've seen on RM before.

Greetings,
Tw0Face
bulmabriefs144
Sexy Alphys!
2525
author=Tw0Face
Wow, I never thought of solving Event problems like that. I think this is an awesome idea and I'll definitely check this out. Especially the way your Stealth System works seems to be an huge improvement towards many other things I've seen on RM before.

Greetings,
Tw0Face

Thanks! Yeah, math was never my favorite subject. I had some Brunhilde-type math teacher with a bossy voice that freaked me out.

The point to everyone (including narcodis just now), is not that this isn't fine code. It's just that people like me for years had that math teacher in their head giving them literal ulcer, that whenever they tried to make games, this said "I could never make a game like that (with guards and ring menus)." I don't mind people good at this using it. But for people who failed trig, my aim is to replace that voice with "I can do this. I'll just do it another way."
Tw0Face
1743
author=bulmabriefs144
Thanks! Yeah, math was never my favorite subject. I had some Brunhilde-type math teacher with a bossy voice that freaked me out.

The point to everyone (including narcodis just now), is not that this isn't fine code. It's just that people like me for years had that math teacher in their head giving them literal ulcer, that whenever they tried to make games, this said "I could never make a game like that (with guards and ring menus)." I don't mind people good at this using it. But for people who failed trig, my aim is to replace that voice with "I can do this. I'll just do it another way."

Sorry, but my post was actually meant to adress Kazesui and his trigonometry script.

Greetings,
Tw0Face
narcodis
heaviness
3499
author=bulmabriefs144
I don't mind people good at this using it. But for people who failed trig, my aim is to replace that voice with "I can do this. I'll just do it another way."

If you dont mind people using trig to solve problems, seems kinda weird youd seek out this one eight-years-old tutorial about how to use trigonometry in an engine that doesnt normally support trigonometry to tell everyone how trig isnt necessary.
bulmabriefs144
Sexy Alphys!
2525
If you dont mind people using trig to solve problems, seems kinda weird youd seek out this one eight-years-old tutorial about how to use trigonometry in an engine that doesnt normally support trigonometry to tell everyone how trig isnt necessary.

I don't actually know how I found it. Oh wait, yes, I do.

I was searching for a good tutorial on how to make Ring Menus. Found this instead. Found it worse than useless, and had to puzzle through over the next few days what to do instead. So it was a sort "thanks for nothing" type thing that inspired me to go after this topic. And ummm, the attitude most of the people here that you "have to know trig" to do this sorta stuff doesn't help matters.

What if you decide you need more menu items? Perhaps an arbitrary number of them that can change? What if you want to resize the ring? Sure, you can write code to cover each possibility, but it would sure be nice to just pass a number or two into a function call and have the code do the rest. That's all the tutorial is addressing.

Then you literally just draw more. You can have up to fifty objects, and that limit is mainly cuz you can have up to 50 pictures (without extending the limit). My sample program had minimum about 3 icons, but about 8, after you collected certain items. It's also fairly easy to learn and use, once you have a KeyPress event.

For the record, this isn't even about the math. Nor is it about Kazesui's code. Alot of his stuff is good. It's about elegant solutions vs simple ones. And it's about most of the people here acting like any other methods are worthless.

The menu could rotate around, but this is a matter of redrawing all locations of each icon. This would be one thing that the trig would be useful for. If you have locational movement, it takes the constant recreating in order to make the same effect as a variable that did it for you. If I decided to use this menu for magic or items, I probably would also use the trig method.

Since I casually wanted a Ring Menu in my game, this thread annoyed and frustrated me, because it was vaguely like someone trying to teach me the entire Chinese language, when I want to know how to say a single word ("thank you") in another language.
If I have to learn an entire mindset just to do one job, I'm not happy.

When I'm on page 5 or so of a search, and nobody has done a more direct tutorial, also not happy.

When I try to explain, that perhaps there must be a simpler way, maybe not as powerful, but simpler, and everyone assumes I'm trashing Kazesui's code, and gives me grief then I'm no longer not happy, but actually pissed off.
narcodis
heaviness
3499
author=bulmabriefs144
When I try to explain, that perhaps there must be a simpler way, maybe not as powerful, but simpler, and everyone assumes I'm trashing Kazesui's code, and gives me grief then I'm no longer not happy, but actually pissed off.

You do you, my friend. I don't believe this tutorial was ever trying to say there wasn't a simpler way to do a certain thing. Peace be with you.
Pages: first prev 123 next last