• 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!

GameMaker [SOLVED] Movement Using Cumulative Speeds

S

Spencer S

Guest
So I have a script that the player executes that controls movement.
playerRunSpeed is set to 90.
playerDiagonalRunSpeed is set to 63.
xAcceleration is set to 6.
yAcceleration is set to 6.
yCurrentSpeed is updated every step of the game based on what has happened to it before.
xCurrentSpeed is the same way, but for the x axis.

The bugs are this: when I hold down up AND right, or down AND right, the y axis never stops accelerating as long as a button is held down, and the x axis stops accelerating completely until all buttons are released. And the player will skid to a stop if they are moving right or down, but not left or up. If they are moving left, or up, they stop immediately. AND, if I press up AND right, or down AND right, and then release right, the player still moves at the same speed before releasing the button until I release all keys.

Tl;dr there's a lot of weird interactions when holding down multiple buttons, and the player won't skid to a stop when moving left or up and all buttons are released. What are my flaws?
Code:
if key_up {
    if (yCurrentSpeed < playerRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        yCurrentSpeed = playerRunSpeed;
    }
}
else if key_left {
    if (xCurrentSpeed < playerRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else {
        xCurrentSpeed = playerRunSpeed;
    }
}
else if key_down {
    if (yCurrentSpeed < playerRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        yCurrentSpeed = playerRunSpeed;
    }
}
else if key_right {
    if (xCurrentSpeed < playerRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else {
        xCurrentSpeed = playerRunSpeed;
    }
}
else if key_up && key_right {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_up && key_left {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_down && key_left {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_down && key_right {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if (!key_up) && (!key_left) && (!key_down) && (!key_right) {
    if (xCurrentSpeed > 0) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed > 0) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        yCurrentSpeed = 0;
        xCurrentSpeed = 0;
    }
}

// Move the player
x += xCurrentSpeed;
y += yCurrentSpeed;
 

Smiechu

Member
Try to change the order of your if's...

First give combined movements, than single movements...

Currently is so that even if you have two keys pressed then the first in order to be executed is the single movement...
 

Slyddar

Member
That's quite a tree structure. You've found one of the problems in using so many nested ifs for movement. The problem is if you are holding 2 keys, the single key code is getting run first and the else structure means the code for both keys is getting bypassed.
 
S

Spencer S

Guest
So I swapped the order of the if statements, so now it looks like this:
Code:
if key_up && key_right {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_up && key_left {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_down && key_left {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_down && key_right {
    if (xCurrentSpeed < playerDiagonalRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else if (yCurrentSpeed < playerDiagonalRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        xCurrentSpeed = playerDiagonalRunSpeed;
        yCurrentSpeed = playerDiagonalRunSpeed;
    }
}
else if key_up {
    if (yCurrentSpeed < playerRunSpeed) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        yCurrentSpeed = playerRunSpeed;
    }
}
else if key_left {
    if (xCurrentSpeed < playerRunSpeed) {
        xCurrentSpeed -= xAcceleration;
    }
    else {
        xCurrentSpeed = playerRunSpeed;
    }
}
else if key_down {
    if (yCurrentSpeed < playerRunSpeed) {
        yCurrentSpeed += yAcceleration;
    }
    else {
        yCurrentSpeed = playerRunSpeed;
    }
}
else if key_right {
    if (xCurrentSpeed < playerRunSpeed) {
        xCurrentSpeed += xAcceleration;
    }
    else {
        xCurrentSpeed = playerRunSpeed;
    }
}
else if (!key_up) && (!key_left) && (!key_down) && (!key_right) {
    if (xCurrentSpeed > 0) {
        xCurrentSpeed -= xAcceleration;
    }
    else if (yCurrentSpeed > 0) {
        yCurrentSpeed -= yAcceleration;
    }
    else {
        yCurrentSpeed = 0;
        xCurrentSpeed = 0;
    }
}
But still, it acts funky. And when holding left or up at all, even if not holding other buttons or without pressing buttons previously, the obj_player endlessly accelerates.
 

TheouAegis

Member
You are using else when you don't need to. Read through your code and think about it logically. I will give you a hint, it's in your diagonal movement half.
 
S

Spencer S

Guest
Ah, that was it! Thanks a ton! I fixed a couple lines and it works like a dream. Thanks!
 
Top