Legacy GM How to normalize diagonal movement without vector?

R

rodrick160

Guest
Im using a script that essentially checks whether there is a wall in the direction your about to move in, and if not, moves you there. I'm not looking for anything fancy, just a simple formula using hspeed and vspeed and maybe some other variables that will set it to move the same speed diagonally as it does horizontally and vertically. Thanks!

My movement script:
Code:
///Move Up
if !(collision_rectangle(x+1,y-var_speed,x+31,y,obj_wall,false,true))
    vspeed=var_speed*-1
else
    vspeed=0
 
not totally sure what your question is but hspeed and vspeed can be normalized by dividing by speed. you'll need to use a temporary variable, because if you do hspeed /= speed, it will change the value of speed at the same time, and then vspeed will have a wrong value.

var _speed = speed;
hspeed /= _speed;
vspeed /= _speed;

However, if you are using 8-directional movement. You can stop extra diagonal speed like this:
if (speed > max_speed) { speed = max_speed; }
 

Surgeon_

Symbian Curator
You can think of it like this:
You have two variables, var_speed and direction.
You can represent that movement with trigonometric functions like this:
hspeed=+var_speed*cos(direction), and
vspeed=-var_speed*sin(direction) //Minus here because in Game Maker the Y axis is inverted.
Since sin(a)^2+cos(a)^2=1, the total speed will always be equal to var_speed.

With that said, if you just want simple 45-degree diagonal movement, you just need to set
vspeed=+/-var_speed/sqrt(2), and
hspeed=+/-var_speed/sqrt(2).

If you don't know trigonometry, I suggest you learn it. I know it's been an irreplaceable tool for me ever since I've learned it in school.

-Surgeon_
 
R

rodrick160

Guest
With that said, if you just want simple 45-degree diagonal movement, you just need to set
vspeed=+/-var_speed/sqrt(2), and
hspeed=+/-var_speed/sqrt(2).

If you don't know trigonometry, I suggest you learn it. I know it's been an irreplaceable tool for me ever since I've learned it in school.

-Surgeon_
Im assuming 2 is because of pythagoras and assuming var_speed is 1, right? If it were 4 it would be different?
 

hippyman

Member
I've done some pretty extensive testing with this specific issue and I've learned that the magic constant is 0.707

My solution is usually this

Code:
Create Event:
baseSpeed = 4;
xspeed = 0;
yspeed = 0;

Step Event:
var h,v,diag,moveSpd;
h = key_to_axis(vk_right,vk_left);
v = key_to_axis(vk_down,vk_up);
diag = h != 0 && v != 0;

moveSpd = baseSpd;
if (diag) moveSpd *= 0.707;//if moving diagonally multiply the move speed by the "magical constant"

xspeed = h * moveSpd;
yspeed = v * moveSpd;

//Collision code here

x += xspeed;
y += yspeed;

Here's that key_to_axis script
Code:
///key_to_axis(positive,negative);
return keyboard_check(argument0) - keyboard_check(argument1);
 

Surgeon_

Symbian Curator
Here's an illustration:



As you can see (because of Pythagoras' theorem), for 45-degree diagonal movement hspeed and vspeed will both always be the maximum speed (var_speed in your case) over square root of 2, then multiplied by +1 or -1, based on direction.

You can also use Game Maker's built in "speed" and "direction" variables and all of this Game Maker will work out behind the scenes.

@hippyman 1/sqrt(2)=sin(45)=cos(45)=0.707106781 so your "magic constant" fits with my more mathematical explanation.

-Surgeon_
 
Top