GML how does this code work??

DaHomie

Member
inputDirection = point_direction(0,0,keyRight-keyLeft,keyDown-keyUp);
inputMagnitude = (keyRight - keyLeft != 0) || (keyDown - keyUp !=0);

hSpeed = lengthdir_x(inputMagnitude * speedWalk, inputDirection);
vSpeed= lengthdir_y(inputMagnitude * speedWalk, inputDirection);

x += hSpeed;
y += vSpeed

I dont think I understand how this code fully works. im following along a youtube tutorial and the person didnt really explain very well for me to understand any form of help is appreciated. if you could give me a run down for what does what would be great and helpful please and thank you.
 
It's just a fancy way of making straight and diagonal movement all at once. I admit it's not very readable, and not sure if more efficient than checking separately for the horizontal and vertical speeds.
The way he does it with point_direction looks mehh to me, but it definitely would work.
Sorry if the person who made that reads this!
 

DaHomie

Member
It's just a fancy way of making straight and diagonal movement all at once. I admit it's not very readable, and not sure if more efficient than checking separately for the horizontal and vertical speeds.
The way he does it with point_direction looks mehh to me, but it definitely would work.
Sorry if the person who made that reads this!
oh i see thanks for explaining it to me i thought it did something more than just movement.
 

samspade

Member
To follow up on what @Slow Fingers said, he is using (assuming this is Shaun Spalding) some basic vector ideas to make it so that you move a consistent length in all 8 directions, rather faster along the diagonals. If you're not familiar with how vectors work, take or imagine a sheet of graph paper and plot out a line from 0, 0, to x and y where x and y are the third and fourth components of the point_direction function. While probably a little less efficient code wise, I actually think this would be more readable:

GML:
inputDirection = point_direction(0,0,keyRight-keyLeft,keyDown-keyUp);
inputMagnitude = point_distance(0,0,keyRight-keyLeft,keyDown-keyUp); //this code is wrong as noted by FrostyCat, Nidoking's version is better

hSpeed = lengthdir_x(inputMagnitude * speedWalk, inputDirection);
vSpeed= lengthdir_y(inputMagnitude * speedWalk, inputDirection);

x += hSpeed;
y += vSpeed;
This substitute a true false check with an actual distance check - again to see how it works plot out a line exactly as before except now instead of getting the angle or direction your getting the distance. Then it is just using lengthdir_x/y to get horizontal and vertical components of that vector.

This I think is one of the best intro videos on vectors out there (which is worth watching as they make a lot of things in computer programming much easlier)

 
Last edited:

Padouk

Member
first line does 2 things: A) it compute a vector in space B) it finds the angle for that vector

A)
assuming keyRight, keyLeft, keyDown and keyUp are boolean their values can be either 0 or 1...
if you move left and right at the same time you are not moving... so 1-1 = 0
if you are moving left only 0-1 = -1
if you are mogving right only 1-0 = 1

so it find two points in space ... like (0,0) and (1,0), and build a vector

2nd line does 1 thing: C) it make sure the length of that vector is either 0 or 1

3 and 4th line does 1 thing D) It find a new position following that vector at a fixed distance

E) Last line manually update the position if the object to that new position.

----

updated removed personal comments not relevant to the point
 
Last edited:

TsukaYuriko

☄️
Forum Staff
Moderator
To offer a slightly more technical explanation...

All of the key* variables are, presumably, booleans (true/false) that are being set to the result of keyboard_check every step. In GML, the constants true and false are assigned the values 1 and 0, respectively. Therefore, if the right key is pressed, keyRight will be 1, otherwise it will be 0.

This means that if both right and left are pressed, keyRight - keyLeft will equal 0. If only left is pressed, it'll be -1, and if only right is pressed, it'll be 1. The same goes for up and down.

The first line sets inputDirection by calculating the direction between 0,0 and a second pair of coordinates, which will be in the range of [-1 ~ 1] on both axes. The possible results are in increments of 45 degrees, corresponding to the 8 directions you can create by pressing one or two arrow keys.

The second line sets inputMagnitude by doing two separate checks - first, to see if exactly one of the right or left key was pressed (because if both or none of them were pressed, this would evaluate to 0), and the same for up and down. If either of these is true, inputMagnitude will be true, otherwise it will be false. This will cause the entire statement to be true unless you are either pressing no keys or all keys (and will cause all movement to cease in those cases further down the road).

The third and fourth line calculate how far the instance should move along the x and y axis using the previously defined direction and magnitude. Since the magnitude is a boolean - so 0 or 1 - used in a multiplication, if the check on line 2 was false, the movement speed will be 0, thus no movement will occur (or to be very specific, a movement of 0 will occur).
 

FrostyCat

Member
@samspade :

Your code is not equivalent to the original, and only the original one is correct in terms of uniform speed.

Here's the original:
GML:
inputMagnitude = (keyRight - keyLeft != 0) || (keyDown - keyUp !=0);
This inputMagnitude is Boolean, which effectively casts to 0 or 1 in the inputMagnitude * speedWalk that comes later, giving 0 or speedWalk as needed for uniform speed.

Here's your version:
GML:
inputMagnitude = point_distance(0,0,keyRight-keyLeft,keyDown-keyUp);
This inputMagnitude is numeric, and will effectively give either 0, 1, or sqrt(2). That extra sqrt(2) reintroduces the same problem that the code is trying to solve.
 

Nidoking

Member
I'm going to hop on a soapbox and say that anyone who's doing math with booleans should get in the habit of adding "? 1 : 0" to every assignment they do this with. Relying on the definitions "true is 1 and false is 0" is a bad habit that languages including GML unfortunately have supported historically. The following example guarantees that you'll be assigning 1 if the expression is true and 0 if the expression is false, with no possible ambiguity or breakage if, in the future, the black box values of true and false change, and it also works in languages where booleans are an explicitly non-numeric type:

GML:
inputMagnitude = ((keyRight != keyLeft) || (keyDown != keyUp)) ? 1 : 0;
 

samspade

Member
This inputMagnitude is numeric, and will effectively give either 0, 1, or sqrt(2). That extra sqrt(2) reintroduces the same problem that the code is trying to solve.
Yup, I missed that. I was trying to do what Nidoking did correctly which is remove the reliance on true and false being equal to 0 and 1.
 

Nidoking

Member
That could also be resolved with the sign function. When you know the value is non-negative, it's effectively value > 0 ? 1 : 0;
 
Top