• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Smooth Look At

J

Jordan Robinson

Guest
Smooth Look At
Jordan Robinson

GM Version: 1.4.1757
Target Platform: ALL
Download: N/A
Links: N/A

Summary:
This will just be a really quick tutorial showing you how to create a very useful script. It will allow the calling instance to rotate smoothly, either accelerating / decelerating or at a fixed speed, towards a target. It will also allow you to easily set the maximum rotate speed and acceleration properties to make it look perfect for every game.

Tutorial:
First of all, you will need to create a script. I named mine SmoothLookAt but you can name it however you like.

Our new script is going to take 4 arguments. These will be:
  • Target x position
  • Target y position
  • Max rotate speed
  • Damping factor
Those should all be relatively self-explanatory, with the possible exception of the damping factor. We will discuss this later, however, so for now let's just say that it will affect the acceleration.
Code:
//SmoothLookAt(x, y, speed, damping)

var dir, spd, dmp;

dir = point_direction(x, y, argument0, argument1);
spd = max(argument2, 0);
dmp = clamp(argument3, 0, 1);
Let's discuss this first bit of code. I have used a few functions here to help make our script a little bit more user-friendly. They will stop the programmer being able to enter argument values that I haven't designed the script to handle.

First of all, we calculate the direction to the target using the function point_direction.

Secondly, we get the maximum rotate speed from argument2, and use the function max to ensure that the rotating speed is positive or 0.

Finally, we get the damping factor. Now, this value must be between 0 and 1 for it to work properly, so we use the clamp function to ensure that it is.

Next, we will use these variables in order to calculate how much the calling instance should rotate per step. This means that our script will be continuously adding or subtracting from the calling instances image_angle to rotate it.
Code:
image_angle -= clamp(angle_difference(image_angle, dir) * dmp, -spd, spd);
The first thing that this script does is execute the function angle_difference which will return the smallest angle between the calling instances image_angle and the direction to the target. This is important because it means that the calling instance will always rotate in the shortest direction to the target which is what we want!

Now, if we got rid of the rest of that aiming code and just used the angle_difference function then the calling instance would just snap to the target direction. Instead, we want to be able to add a bit of acceleration to it. This is where the damping factor comes into play. By multiplying the angle_difference by dmp it will lerp the value. This can be better explained with an example:
Let's say the angle_difference was 90. If the damping factor was 0.5, then rather than rotating 90 degrees and snapping to the target, the calling instance would rotate 45 degrees. Now remember that this is being called every step which means the next step the instance will rotate 22.5 degrees and so on. This will effectively make it appear to accelerate and rotate much more smoothly.

Finally, the last step of the process is to limit the rotating speed. We do this by using a clamp function again, with -spd and spd as the min and max values respectively. We have to have a negative speed as well because the calling instance should be able to rotate in both directions.

The final step is to apply the result to the calling instances image_angle. This is done by subtracting, which is due to the way angle_difference works. Check out the link above for more info.

The final script should look like this:
Code:
//SmoothLookAt(x, y, speed, damping)

var dir, spd, dmp;

dir = point_direction(x, y, argument0, argument1);
spd = max(argument2, 0);
dmp = clamp(argument3, 0, 1);

image_angle -= clamp(angle_difference(image_angle, dir) * dmp, -spd, spd);
Play around with different values and see how it affects the rotational motion of the calling instance. You can make it quick, slow, loose, or mechanical looking just by altering the speed and damping values.

Hopefully this tutorial was helpful. Cheers.
 

Strobosaur

Member
Thanks for taking the time to write this! I will most likely find this very helpful, because for some reasone, although math was my favourite subject for most of my early youth, for some reason our teacher choose to skip the whole chapter dealing with angles, spheres and circles in general (and i apparently never managed to learn it by myself). So even though i feel a lot of mathematics have returned after many years of dormancy, as i have been getting more and more into game maker and game making, this area is still something i struggle with every time i need to do it... I will return here many times im sure, easy to read and grasp, very nice :)
 
Top