I don’t know if this is a tutorial or something. I just want to share to you guys the possible applications of Sine and Cosine functions besides calculating angles.
The Math.sin()
and Math.cos()
functions are pretty interesting. Both of these functions takes in a number(in radians, but more in that later) and returns a value from -1 to 1. One thing I want to point out is that these values oscillate. Like from 0 to 0.5 to 1 to 0.5 to 0 to -0.5 to -1 to -0.5 to 0 to 0.5 to 1 etc.
I hope you get analogy because I’ll be playing with that analogy throughout this tutorial/article/whatever. Assuming you are on a swing(a real swing, not the wrecking ball unless your Miley jk), there are 3 things that you can easily observe.
These are all the information you need to make use of these functions creatively. One other thing, we all know that everything runs relative to time. And so thus when we are swinging. For the swing to “swing”, time should exist. So now, let’s go to the math and codes.
Simulate time
// Initialize the "time" variable to something. I prefer setting it to zero
var time:Number = 0;
...
...
...
// I suggest you do this PART in an update function
time += FP.elapsed;
The Function
// BASIC FORM
// Pass in the time variable.
value = Math.sin(time);
// IMPORTANT: The time determines the value returned BUT the rate at which the time is changing determines the "How fast is this swing swinging?"
To make it clear, assume your in a swing again. If the time passes by normally, at a rate of 1 second every second(I hope it makes sense) then the swing will swing at a normal speed. But if the time passes by TWICE as fast, at a rate of 2 seconds every second then the swing would swing TWICE as faster. Another way of thingking about it is when your watching a movie about a swinging swing(best movie ever) and hit the fast forward button, the swing in the movie would swing much faster. And also, the opposite is also true. A slower time would equate to a slower swing. In a more mathematical sense, the change in time is directly proportional to the speed of the of the swing. Whew, okay. I think you get the point. So now I’d like to introduce you to another form.
The Time Bender
value = Math.sin(timer * HowFastTimeIs);
// Let's say that if HowFastTimeIs = 1 the swing would swing normally
// Then HowFastTimeIs = 2, the swing would swing 2 times as normal
// HowfastTimeIs = 1/2, the swing would swing at half the speed as normal
By chaging how fast time is, you can control the speed of the swing. Now, the last thing we didn’t cover is about the distance from each end. But, we will actually use the distance from the center of the swing to the farthest end.
The Distance
// Notice that this distance is not the distance in the picture but the distance from the center to any farthest side
value = Math.sin(time) * DistanceFromTheCenterToAnySide;
// What happens here is that the value will oscillate from -DistanceFromTheCenterToAnySide to +DistanceFromTheCenterToAnySide
// Just imagine replacing the -1 and 1 in the picture
// So if the distance is 5, the values will oscillate between -5 and 5
And lastly, the ultimate form. This is what I use in my projects.
The Ultimate Form
value = Math.sin(time * HowFastTimeIs) * DistanceFromTheCenterToAnySide;
Using this, you can get values that oscillates between any point and control how fast it oscillates.
So… That’s basically how I use these functions. But how exactly do you use this? For what purpose? Well, in my case, it’s what the title said. Here are some examples.
Patrolling enemy in a platformer
I want an enemy to patrol between two places. Assuming the movement is purely horizontal:
// First, get the distance. Distances are always positive, so get the absolute value.
var DistanceFromCenterToAnySide:Numbe = Math.abs(xCenter - xEnd);
// This is equal to 70
...
...
...in the Enemy Update code
x = xCenter + (Math.sin(timer * HowFastTimeIs) * DistanceFromCenterToAnySide);
// As you can notice, I didn't set the how fast the time thing. You can basically experiment on its value until you get the right speed that you want.
Another important concept is what I call the central point of the swing. This is the point where the values will oscillate around. In the above codes above this code, the values will just oscillate around 0. But in here, we want the enemy to move around x = 105, so how do we do that? It’s easy, just add 105. Here is a more general form:
The Super Ultimate Form
value = CenterOfTheSwing + Math.sin(time * HowFastTimeIs) * DistanceFromTheCenterToAnySide;
This is the most powerful form. And with great power comes great reponsibility, so use it with care. Make sure you understand every part of this form.
So moving on, here are other examples to give you some idea:
-
Change the scale of an image so that it mimics the pumping of the heart.
-
Manipulate an entity to make it seem that it is floating in water. Like in a rising up then falling down manner just like when you are swimming at the beach as the waves hits you.
-
Repetitive crushing motion of 2 walls. Like when you clap, assume that your hands are the walls.
-
A looping timer. This is a bit more tricky. So I’m gonna explain this.
Looping Timer
I want an event to happen every t seconds. One way of doing this is actually implementing a timer. But let me show you how it can be done using the Time Bender. Basically, you need to set the HowFasttTimeIs into an accurate value to represent t seconds.
// Assume we calculate HowFastTimeIs here
if (Math.sin(timer * HowFastTimeIs) == 0)
{
// Do Event here
}
But how do we calculate that? Using this:
var HowFastTimeIs:Number = 2 * Math.PI / t;
The sine function will return the same value every 2 * Math.PI
radians or one full oscillation. Don’t mind the radians, it’s just a fancy name for a special number(this is the “more on that later” on the first part). So what I want is that the value 0 will come up every t seconds. So what I did is to get how much the swing should oscillate every second. That should give us the desired swing.(I don’t think I explained this well. My apologies.) But there is some problem, this will only work for as long as the computer can calculate accurate results. There are cases where computations aren’t accurate. Such things like 0.0000023 == 0
might happen which will evaluate to false. So please, try to refrain from using looping timers in actual projects. The main reason I mentioned this is to introduce how to calculate for the exact timings of oscillation. So you can use that HowFastTimeIs code to specify the speed of oscillation on your projects. Like how fast should the enemy moves in the platformer example above.
So let me end this with some tips and other stuff.
-
All codes in this article should not be taken as a law or something. As long as you get how the function behaves and how you can manipulate it, you should be able to use it correctly and bend it to you will(such words of wisdom).
-
When using Math.cos(), the only difference is that when Math.cos() is 0, Math.sin() is either 1 or -1. When Math.sin() is 0, Math.cos() is either -1 or 1. So keep that in mind.
-
The examples above only manipulates one variable. You can use this technique in two or more related variables to create to create intersting results. Such as an enemy moving in a circle(I suggest you check FP.rotateAround() for this. This will be an fun exercise regardless.) or moving on an infinity shaped path(both manipulating x & y positions).
-
The one thing which breaks the Swing Analogy is when you try to travel back in time. In the real world, you can’t do that. But in here, it’s allowed. If the time progresses towards the negative direction, the oscillation will just reverse.
-
This technique is useful for graphical effects. Though it can impact performance. In prototypes where performance is not that much of a problem and your graphical talent sucks(like me), this technique MAY suffice.
-
Another Swing Analogy breaker, stopping of time. You can choose not to update time. This can create cool effects such us… I don’t know hahaha. Maybe you can think of something.
So that’s it. Thanks for reading I really do hope that what I did here was helpful. If I fail on some parts(or all of it), please do tell me. I won’t mind.