diagonal speed

P

piksil_demon

Guest
can someone please tell me how to make my diagonal speed equal to my hspd and vspd in this code?
x += (right - left) * spd;
y += (down - up) * spd;


as of now the diagonal is noticeably faster
 

GMWolf

aka fel666
Code:
dx = (right - left);
dy = (down - up);
dl = sqrt(dx*dx + dy*dy);
dx *= spd / dl;
dy *= spd / dl;
Will work for any value dx and dy. So you can use controlers, acceleration, etc.
You speed will always be spd.
 
P

piksil_demon

Guest
Code:
dx = (right - left);
dy = (down - up);
dl = sqrt(dx*dx + dy*dy);
dx *= spd / dl;
dy *= spd / dl;
Will work for any value dx and dy. So you can use controlers, acceleration, etc.
You speed will always be spd.
what is dy and dx? i dont have that in my code
 
P

piksil_demon

Guest
Going by your OP, it was safe to assume that you were using 8 directions.

If this is the case then, yes, multiplying by 0.7071 is exactly what you want.
where are you getting that number? it seems that it is a square root of a number and in which case it isnt becasue it would be an irrational number
 
okay, so if you've got a hspeed and vspeed like this:

xsp = (right - left) * spd;
ysp = (down - up) * spd;

then to correct for the diagonal speed boost, all you have to do is this:

if (xsp != 0) and (ysp != 0) { xsp *= sqrt(0.5); ysp *= sqrt(0.5); }

If you were using the built-in variables hspeed, and vspeed (which you should unless you have a good reason for not doing so), then all you would have to do is this:

if (speed > spd) { speed = spd; }

if you have some random direction and speed, you can make sure the speed is exactly equal to spd, while maintaining the same direction, like this:

var _m = spd / sqrt(xsp * xsp + ysp * ysp); //(will get divide by zero error if xsp and ysp are both zero)
xsp *= _m;
ysp *= _m;

but again, if you were using the built in movement variables, all you would have to do is:

speed = spd;
 
P

piksil_demon

Guest
okay, so if you've got a hspeed and vspeed like this:

xsp = (right - left) * spd;
ysp = (down - up) * spd;

then to correct for the diagonal speed boost, all you have to do is this:

if (xsp != 0) and (ysp != 0) { xsp *= sqrt(0.5); ysp *= sqrt(0.5); }

If you were using the built-in variables hspeed, and vspeed (which you should unless you have a good reason for not doing so), then all you would have to do is this:

if (speed > spd) { speed = spd; }

if you have some random direction and speed, you can make sure the speed is exactly equal to spd, while maintaining the same direction, like this:

var _m = spd / sqrt(xsp * xsp + ysp * ysp); //(will get divide by zero error if xsp and ysp are both zero)
xsp *= _m;
ysp *= _m;

but again, if you were using the built in movement variables, all you would have to do is:

speed = spd;
that solution works, thank you. and my reasons for using my variables are my own :)
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Just so you know, you can also do this (which I find more intuitive):

Code:
var xsp = (right - left)
var ysp = (down - up);
var d = point_direction(0, 0, xsp, ysp);
x += lengthdir_x(spd, d);
y += lengthdir_y(spd, d);
;)
 
  • Like
Reactions: Roa
P

piksil_demon

Guest
Still unnesseary code bloat if the movement is only 8 directions. But the OP hasn't really clarified that yet.
i shouldnt have to specify an 8 directional movement as the code i provided is intended to allow 8 directional movement, no more, no less
 
P

piksil_demon

Guest
Just so you know, you can also do this (which I find more intuitive):

Code:
var xsp = (right - left)
var ysp = (down - up);
var d = point_direction(0, 0, xsp, ysp);
x += lengthdir_x(spd, d);
y += lengthdir_y(spd, d);
;)
thank you. this works aswell, and is very coherent
 

NightFrost

Member
Well, the code could be simplified. Since it is expressly stated movement is always 8-way, there's no point (ha) in point_direction. And we know lengthdir_* is just a wrapper to hide trig from newbies, so you could do sin/cos yourself. But since the angle (of the right-handed triangle) is always the same, you end up with dsin or dcos 45 which you could put into a constant. Or, you know, jsut put 0.7071 to that constant to save a trig call on create event.
 

GMWolf

aka fel666
Sigh.
This is slowly gonna become a code clarity vs performance issue isnt it.
Anyhow, this is bery basic vector maths. No need for trigonometry.
In fact, most of the solutions here use vector maths:
1. Get direction vector.
2. Normalize it by dividing by its length.
3. Multiply that by the desired speed.

Only edge case is when no keys are pressed. Just use an if statement to escape that and void division by 0.
 
M

Maximus

Guest
Going by your OP, it was safe to assume that you were using 8 directions.

If this is the case then, yes, multiplying by 0.7071 is exactly what you want.
I agree with lonewolf here. If your using discrete buttons (like a d-pad or keyboard arrows), then multiplying by 0.7071 would be the most efficient way to 'normalise' the vector. If you want joystick sort of behaviour (that doesn't do this automatically for some reason) you would need to do the more involved calculation.

here's what the trig might look like:
Code:
var dir, dist;
dir = degtorad(point_direction(0, 0, joy_x_raw, joy_y_raw));
dist = min(1, point_distance(0, 0, joy_x_raw, joy_y_raw));
joy_x = cos(dir) * dist;
joy_y = -sin(dir) * dist;
 

GMWolf

aka fel666
so yes, it is irrational. meaning .7071 isnt good enough. i need a different solution (and no, more digits isnt that solution)
You know computers dont have infinite precision.
When you call sqrt(2), its just an aproximation, not exact value.
So first of all, .7071 is probably good enough unless you work for CERN.
Second. All the vector solutions are eventually simply multiplying by .7071(+a few digits)
Third, all the trig solutions are even less accurate (than vector) since trig functions are approximated. Though it still doesnt matter.

For 8 dir movement, multiplying by .7071 is actually probably the clearest solution. Just make sure to create a variable called root2 or something so it makes more sense...
The vector solutions are nice if you want more than 8 directions.
And the trig solutions are just unecesarily complicated. I dont know why people find trigonometry ewsier than vectors... vectors are super simple!
 

RangerX

Member
What if I use a mix of impulse and X and Y position? My character using hspeed to move left and right and my slope code bumps up or down my character like (y-1) to "climb" every pixel...

Here's what I do but I feel I am missing something. Seems to look fine on 45 degrees climb but the character feels slow climbing some 15 degrees slopes.

Code:
if((speed>i_HspeedMax)&&(b_HeroOnSlope==true)&&(b_HeroIsGliding==false))
then
{
speed=i_HspeedMax/sqrt(2);
}
 
Last edited:
M

Maximus

Guest
Anyhow, this is bery basic vector maths. No need for trigonometry.
whether or not you explicitly use trig doesn't change the fact that it will be used internally. Multiplying by 0.7071 is the only method above that eliminates the need for the computer to do that calculation.
 

GMWolf

aka fel666
whether or not you explicitly use trig doesn't change the fact that it will be used internally. Multiplying by 0.7071 is the only method above that eliminates the need for the computer to do that calculation.
What? No, you can use vector maths.
Infact, multiplying by .707 is vector maths, but just for a specific case.

If you look above, plenty of people including myself have posted non trig vector solutions.
 
M

Maximus

Guest
What? No, you can use vector maths.
Infact, multiplying by .707 is vector maths, but just for a specific case.

If you look above, plenty of people including myself have posted non trig vector solutions.
Pythagorus is trig, lengthdir_x/y is trig, point_direction / point_distance is trig.
 
M

Maximus

Guest
For 8 dir movement, multiplying by .7071 is actually probably the clearest solution. Just make sure to create a variable called root2 or something so it makes more sense...
You could do what fel666 said but store it as root2 = sqrt(2); if you want to have the illusion of accuracy and still maintain performance.
 

NightFrost

Member
I dont know why people find trigonometry ewsier than vectors... vectors are super simple!
Going off a tangent (ho ho) here, but does GM2 support vectors as a variable type? As in declaring something like Coords vec2 (10, 10)? That would make wrangling them... easier.
 
Going off a tangent (ho ho) here, but does GM2 support vectors as a variable type? As in declaring something like Coords vec2 (10, 10)? That would make wrangling them... easier.
You could create some scripts that fill the gap in GML functionality in this regard. Scripts, that do all the arithmetic and return an array or real value, depending on the function.
 
Top