GMS 2 Unbiased 4-Directional Movement With Diagonal Movement

Hi there

So I want to have 4-directional movement but still allow for diagonal movement. It's just basically the movement Undertale has but I just don't know how to make it work properly.

what I have now is:

GML:
/// Create Event
plyrspeed = 2;
// I need to work with directions like this because I have something else that needs the players direction
enum dir {
    right,
    left,
    up,
    down
}

/// Step Event
// INITIAL SPRITE SETTING
// The variable "direc" is fed to the player by a different object when it's created
switch(direc) {
    case dir.right: sprite_index = spr_plyrright; break;
    case dir.up: sprite_index = spr_plyrup; break;
    case dir.left: sprite_index = spr_plyrleft; break;
    case dir.down: sprite_index = spr_plyrdown; break;
}

// INPUT
moveX = (keyboard_check(vk_right) - keyboard_check(vk_left)) * plyrspeed;
moveY = (keyboard_check(vk_down) - keyboard_check(vk_up)) * plyrspeed;

// COLLISION DETECTION
if(moveX != 0) {
    if(place_meeting(x + moveX, y, obj_collision)) {
        repeat(abs(moveX)) {
            if(!place_meeting(x + sign(moveX), y, obj_collision))  { x += sign(moveX);}
            else { break;}
        }
        moveX = 0;
    }
}

if(moveY != 0) {
    if(place_meeting(x, y + moveY, obj_collision)) {
        repeat(abs(moveY)) {
            if(!place_meeting(x, y + sign(moveY), obj_collision))  { y += sign(moveY);}
            else { break;}
        }
        moveY = 0;
    }
}

// SPRITE CHANGING
if(moveX != 0 or moveY != 0) {
    image_speed = 1;
    if(moveX == 0) {
        if(moveY > 0) {
            direc = dir.down;
        }
        if(moveY < 0) {
            direc = dir.up;
        }
    }
    if(moveY == 0) {
        if(moveX > 0) {
            direc = dir.right;
        }
        if(moveX < 0) {
            direc = dir.left;
        }
    }
}
else {
    image_speed = 0;
    image_index = 0;
}

// ACTUAL MOVEMENT
x += moveX;
y += moveY;
This kind of works but it's a little wonky. For example: If you press left and right and then press up the player won't go up but if you press left and right and then press down the player will go down. Also because you don't move upwards like that the sprite doesn't change if you stop pressing either left or right so it looks like the player is doing a moonwalk. This also goes for pressing up and down and then pressing left.

I'm doing all of this so weirdly because I don't want the direction the player is looking in to be biased. In other words I don't want the player's sprite to prioritise looking in a certain direction because of the order it checks the direction in.

Please help I've been working on this simple movement for way too long and I'm starting to feel like I actually don't have a brain and I'm living on pure willpower. Thanks in advance!
 

Sybok

Member
Next problem you'll have is that the diagonal movement will be 1.41x faster than the horizontal and vertical movement.
 

TheouAegis

Member
If you press left and right and then press up the player won't go up
You mean all 3 directions at once? That's keyboard ghosting. Your down key is mapped to a different circuit than up, left and right, which is why down works but not up.

I also don't think you should be setting the sprite direction after you handle collisions since your collision code is modifying your vectors as well.
 
Last edited:
You mean all 3 directions at once? That's keyboard ghosting. Your down key is mapped to a different circuit than up, left and right, which is why down works but not up.

I also don't think you should be setting the sprite direction after you handle collisions since your collision code is modifying your vectors as well.
But isn't that exactly the reason why I would want the sprite to change after the collisions modify my vectors? I mean I wouldn't want my player to be moving even though he stopped. What am I missing here?
 
Top