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

GML How to stop diagonal movement

W

William Turner

Guest
As the title says i'm trying to stop the diagonal movement...All my attempts to fix the problem my self have failed miserably...

Code i'm using for movement
Code:
//MOVEMENT
//check

if(keyboard_check(ord("W")))
{    y = y - 5;
    sprite_index = spr_player_blue_up

}

if(keyboard_check(ord("A")))
{    x = x - 5;
    sprite_index = spr_player_blue_left

}

if(keyboard_check(ord("S")))
{    y = y + 5;
    sprite_index = spr_player_blue_down

}

if(keyboard_check(ord("D")))
{    x = x + 5;
    sprite_index = spr_player_blue_right
  
}

//check

//Released

if(keyboard_check_released(ord("W")))
{
    sprite_index = idle_up
  
}
if(keyboard_check_released(ord("A")))
{
    sprite_index = idle_left
  
}
if(keyboard_check_released(ord("S")))
{
    sprite_index = idle_down
  
}
if(keyboard_check_released(ord("D")))
{
    sprite_index = idle_right
  
}

//Released
//MOVEMENT
If anyone has any suggestions or know a tutorial I should look at please let me know.
 
Last edited by a moderator:

Relic

Member
After the first keyboard check, rather than using if, use else if.

This will make all keyboard checks conditional on each other too.

A simple solution but it would mean keyboard checks higher up in the code will have priority over others below it
 
F

Frozen Stick

Guest
You could also make a variable named for example move in the create event of the object and when you press the (W or A or S or D) key you set it to 1 and you can use the code to set the variable to 0:
Code:
if move = 1 and ( !(keyboard_check(ord("W"))) or !(keyboard_check(ord("A"))) or !(keyboard_check(ord("S"))) or !(keyboard_check(ord("D")))  ) move = 0;
kinda messy but gets the job done.
 
D

dannyjenn

Guest
What do you want it to do if the player presses e.g. W and D at the same time? Should the player not move at all? Or do you want him to move, but you want it to prioritize horizontal movement over vertical movement, or vice versâ?

You could do something like this:
Code:
// player doesn't move at all if two or more WASD keys are pressed

var input = (keyboard_check(ord("W"))<<3) | (keyboard_check(ord("A"))<<2) | (keyboard_check(ord("S"))<<1) | (keyboard_check(ord("D")));
switch(input){
    case 8: // %1000, i.e. W only
        y -= 5;
        sprite_index = spr_player_blue_up;
        break;
    case 4: // %0100, i.e. A only
        x -= 5;
        sprite_index = spr_player_blue_left;
        break;
    case 2: // %0010, i.e. S only
        y += 5;
        sprite_index = spr_player_blue_down;
        break;
    case 1: // %0001, i.e. D only
        x += 5;
        sprite_index = spr_player_blue_right;
        break;
    default: // two or more WASD keys at the same time, or no WASD key at all
        switch(sprite_index){
            case spr_player_blue_up:
                sprite_index = idle_up;
                break;
            case spr_player_blue_left:
                sprite_index = idle_left;
                break;
            case spr_player_blue_down:
                sprite_index = idle_down;
                break;
            case spr_player_blue_right:
                sprite_index = idle_right;
                break;
        }
}
or this:
Code:
// horizontal movement is prioritized over vertical

var input = (keyboard_check(ord("W"))<<3) | (keyboard_check(ord("A"))<<2) | (keyboard_check(ord("S"))<<1) | (keyboard_check(ord("D")));
switch(input){
    case 8: // %1000, i.e. W
    case 13: // %1101, i.e. W, A, and D
        y -= 5;
        sprite_index = spr_player_blue_up;
        break;
    case 4: // %0100, i.e. A
    case 14: // %1110, i.e. A, W, and S
    case 12: // %1100, i.e. A and W <-- prioritize horizontal movement
    case 6: // %0110, i.e. A and S <-- prioritize horizontal movement
        x -= 5;
        sprite_index = spr_player_blue_left;
        break;
    case 2: // %0010, i.e. S
    case 7: // %0111, i.e. S, A, and D
        y += 5;
        sprite_index = spr_player_blue_down;
        break;
    case 1: // %0001, i.e. D
    case 11: // %1011, i.e. D, W, and S
    case 9: // %1001, i.e. D and W <-- prioritize horizontal movement
    case 3: // %0011, i.e. D and S <-- prioritize horizontal movement
        x += 5;
        sprite_index = spr_player_blue_right;
        break;
    default: // W and S; A and D; W, A, S, and D; or no WASD keys
        switch(sprite_index){
            case spr_player_blue_up:
                sprite_index = idle_up;
                break;
            case spr_player_blue_left:
                sprite_index = idle_left;
                break;
            case spr_player_blue_down:
                sprite_index = idle_down;
                break;
            case spr_player_blue_right:
                sprite_index = idle_right;
                break;
        }
}
or this:
Code:
// vertical movement is prioritized over horizontal

var input = (keyboard_check(ord("W"))<<3) | (keyboard_check(ord("A"))<<2) | (keyboard_check(ord("S"))<<1) | (keyboard_check(ord("D")));
switch(input){
    case 8: // %1000, i.e. W
    case 13: // %1101, i.e. W, A, and D
    case 12: // %1100, i.e. W and A <-- prioritize vertical movement
    case 9: // %1001, i.e. W and D <-- prioritize vertical movement
        y -= 5;
        sprite_index = spr_player_blue_up;
        break;
    case 4: // %0100, i.e. A
    case 14: // %1110, i.e. A, W, and S
        x -= 5;
        sprite_index = spr_player_blue_left;
        break;
    case 2: // %0010, i.e. S
    case 7: // %0111, i.e. S, A, and D
    case 6: // %0110, i.e. S and A <-- prioritize vertical movement
    case 3: // %0011, i.e. S and D <-- prioritize vertical movement
        y += 5;
        sprite_index = spr_player_blue_down;
        break;
    case 1: // %0001, i.e. D
    case 11: // %1011, i.e. D, W, and S
        x += 5;
        sprite_index = spr_player_blue_right;
        break;
    default: // W and S; A and D; W, A, S, and D; or no WASD keys
        switch(sprite_index){
            case spr_player_blue_up:
                sprite_index = idle_up;
                break;
            case spr_player_blue_left:
                sprite_index = idle_left;
                break;
            case spr_player_blue_down:
                sprite_index = idle_down;
                break;
            case spr_player_blue_right:
                sprite_index = idle_right;
                break;
        }
}

edit - Another option is to have the game remember the first WASD key that was pressed and then ignore any subsequent WASD keys until that particular key is released. After re-reading your post, perhaps this is what you wanted?
You could do it something like this:
Code:
// create event:
current key = vk_nokey; // no WASD key
Code:
// step event:

// first check for key release and update sprites accordingly
if(keyboard_check_released(ord("W"))){
    current_key = vk_nokey; // no WASD key
    sprite_index = idle_up;
}
else if(keyboard_check_released(ord("A"))){
    current_key = vk_nokey; // no WASD key
    sprite_index = idle_left;
}
else if(keyboard_check_released(ord("S"))){
    current_key = vk_nokey; // no WASD key
    sprite_index = idle_down;
}
else if(keyboard_check_released(ord("D"))){
    current_key = vk_nokey; // no WASD key
    sprite_index = idle_right;
}

// then check for key and update sprites accordingly
if(current_key==vk_nokey){ // <-- this extra if statement is what you need
    if(keyboard_check(ord("W"))){
        current_key = ord("W");
        sprite_index = spr_player_blue_up;
    }
    else if(keyboard_check(ord("A"))){
        current_key = ord("A");
        sprite_index = spr_player_blue_left;
    }
    else if(keyboard_check(ord("S"))){
        current_key = ord("S");
        sprite_index = spr_player_blue_down;
    }
    else if(keyboard_check(ord("D"))){
        current_key = ord("D");
        sprite_index = spr_player_blue_right;
    }
}

// then do the movement (this needs to be separate now, since your above code has been moved to an if statement)
switch(current_key){
    case vk_nokey: // no WASD key
        // no movement
        break;
    case ord("W"):
        y -= 5;
        break;
    case ord("A"):
        x -= 5;
        break;
    case ord("S"):
        y += 5;
        break;
    case ord("D"):
        x += 5;
        break;
}
It's basically the same code you had, except the key check stuff has been moved inside an if statement such that it only ever happens one time until the key is released. (The movement code needs to be separate, since the key check code is now only happening once whereas you want the movement to happen each step.) And I believe the key release code needs to come before the key check code in order to allow for seamless directional change.
It's still not perfect though, since if the player presses e.g. W and S and D within the same step then it's going to ignore the S and the D rather than ignoring the W and the S... but that probably won't happen too often or be too noticeable when it does. Apart from that, the code should work as intended: if the player holds down W and then a little later holds D while still holding W, it ignores the D (he keeps walking up... he does not begin moving up-right or switch to right). But if the player holds D and then a little later holds W while still holding D, it ignores the W (i.e. he continues moving to the right. He does not change to up-right or up).
 
Last edited by a moderator:
Top