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

Legacy GM four directional grid movement issue

Hello, I'm having an issue with my four-directional grid movement code. As you can see in the video below, there is something weird going on with the movement. At certain point near the end I get stuck when reaching the edge of the screen. The movement in general looks weird when the movement keys are held down and not simply pressed. Any ideas how to fix this?
Code:
Create Event:
execute code:

/// Initialize General variables

// Define the current location of the player on the grid
gridX = ( x div global.cellWidth ); // Cell within the row that the player is on (going horizontally) - starting from 0
gridY = ( y div global.cellHeight ); // Cell within the column that the player is on (going vertically) - starting from 0

// Define variables to store the position the player is moving from on the grid.
gridFromX = gridX; // Set to gridX by default since the player is not in the process of moving by default.
gridFromY = gridY; // Set to gridY by default since the player is not in the process of moving by default.

// Define variables to store where the player is moving to on the grid.
gridToX = gridX; // Set to gridX by default since the player is not in the process of moving by default.
gridToY = gridY; // Set to gridY by default since the player is not in the process of moving by default.

//
pState = PLAYER_ST.IDLE; // The state the player is in
pDir = DIR.DOWN; // Direction the player is moving in/facing

//
walkAniLength = 0.5; // The time it will take to cross one cell in seconds.
walkAniTime = 0; // How much of the animation has played out in seconds.

//
walkSpd = 4;
runSpd = walkSpd * 2;
spd = walkSpd;

Step Event:
execute code:

/// Player States
switch( pState )
{
   case PLAYER_ST.IDLE:
  
       if global.charControlEnabled == true && global.inputDisabled == false && global.gamePaused == false
       {
           if keyboard_check( global.leftKey ) && gridX > 0 { srcMovePlayer( DIR.LEFT ); exit; }
           if keyboard_check( global.rightKey ) { srcMovePlayer( DIR.RIGHT ); exit;  }          
           if keyboard_check( global.upKey ) && gridY > 0 { srcMovePlayer( DIR.UP ); exit; }
           if keyboard_check( global.downKey ) { srcMovePlayer( DIR.DOWN ); exit;  }          
       }
  
   break;

   case PLAYER_ST.WALKING:
       var walkTimeLeft = walkAniTime / walkAniLength;
       var movingGridX = lerp( gridFromX, gridToX, walkTimeLeft );
       var movingGridY = lerp( gridFromY, gridToY, walkTimeLeft );
        
   // Gradually increase the walkAniTime variable to indicate how many seconds the player walking animation has played.  
       walkAniTime += spd * ( 1 / room_speed );
      
     // Set the new x and y coordinates by multiplying the value between two points interporlated by the walking time by the cell width/height.
       x = ( movingGridX * global.cellWidth );
       y = ( movingGridY * global.cellHeight );
      
       if walkTimeLeft >= 1
       {
           walkAniTime = 0; // Reset variable
           walkTimeLeft = 1; // Ensure variable doesn't exceed 1
           pState = PLAYER_ST.IDLE; // Change state back to idle                  
       }
      
   break;
  
}
srcMovePlayer()
Code:
/// srcMovePlayer( DIRECTION )
/*
    This script sets the player's grid related position variables and changes the state and direction of the player object prior to moving.
    Pass enum DIR as an argument based on the key pressed by the player.

    The method used to move the player is similar to doing:
        gridToX = gridX + ( keyboard_check( global.leftKey ) - keyboard_check( global.rightKey ) );
        gridToY = gridY + ( keyboard_check( global.upKey ) - keyboard_check( global.downKey ) );

*/
var inputDir = argument0; // The direction the player should move in based on the player's input of either left, right, up, or down.
var addToGridX = 0; // Must be 0 by default.
var addToGridY = 0; // Must be 0 by default.

// Change the value of either addToGridX or addToGridY depending on the key pressed by the player.
if inputDir == DIR.LEFT { addToGridX = -1; }
if inputDir == DIR.RIGHT { addToGridX = 1; }
if inputDir == DIR.UP { addToGridY = -1; }
if inputDir == DIR.DOWN { addToGridY = 1; }

// Set the variables indicating where the player is moving from to the player's current position within the grid.
gridFromX = gridX;
gridFromY = gridY;

// Set the variables indicating where the player is moving to within the grid.
gridToX = gridX + addToGridX;
gridToY = gridY + addToGridY;
  
// Set the current position of the player within the grid.
gridX = gridToX;
gridY = gridToY;
  
// Change the direction and player state.
pDir = inputDir;
pState = PLAYER_ST.WALKING;
 
Last edited:

TheouAegis

Member
Because u are setting the sprite back to idle after every cell. Set it back to idle only if the player isn't trying to move or if he can't walk in the direction he's trying to go.
 
Because u are setting the sprite back to idle after every cell. Set it back to idle only if the player isn't trying to move or if he can't walk in the direction he's trying to go.
Tried this and it didn't work:
Code:
    case PLAYER_ST.WALKING:
        var walkTimeLeft = walkAniTime / walkAniLength;
        var movingGridX = lerp( gridFromX, gridToX, walkTimeLeft );
        var movingGridY = lerp( gridFromY, gridToY, walkTimeLeft );
          
    // Gradually increase the walkAniTime variable to indicate how many seconds the player walking animation has played.  
        walkAniTime += spd * ( 1 / room_speed );
      
      // Set the new x and y coordinates by multiplying the value between two points interporlated by the walking time by the cell width/height.
        x = ( movingGridX * global.cellWidth );
        y = ( movingGridY * global.cellHeight );
      
        if walkTimeLeft >= 1
        {
            walkAniTime = 0; // Reset variable
            walkTimeLeft = 1; // Ensure variable doesn't exceed 1                  
        }
      
        if keyboard_check_released( global.leftKey ) || keyboard_check_released( global.rightKey ) || keyboard_check_released( global.upKey ) ||
        keyboard_check_released( global.downKey )
        {
            pState = PLAYER_ST.IDLE; // Change state back to idle
        }
      
    break;
Also tried:
Code:
if (!keyboard_check( global.leftKey )) && (!keyboard_check( global.rightKey )) && (!keyboard_check( global.upKey )) &&
        (!keyboard_check( global.downKey ))
 
Nothing I'm trying seems to work. Tried doing it this way, but made things worse:
Code:
    case PLAYER_ST.WALKING:   
        if (!keyboard_check( global.leftKey )) && (!keyboard_check( global.rightKey )) && (!keyboard_check( global.downKey )) && (!keyboard_check( global.upKey ))
        {
            var walkTimeLeft = walkAniTime / walkAniLength;
            var movingGridX = lerp( gridFromX, gridToX, walkTimeLeft );
            var movingGridY = lerp( gridFromY, gridToY, walkTimeLeft );
               
        // Gradually increase the walkAniTime variable to indicate how many seconds the player walking animation has played.   
            walkAniTime += spd * ( 1 / room_speed );
           
          // Set the new x and y coordinates by multiplying the value between two points interporlated by the walking time by the cell width/height. 
            x = ( movingGridX * global.cellWidth );
            y = ( movingGridY * global.cellHeight );
       
            if walkTimeLeft >= 1 
            {
                walkAniTime = 0; // Reset variable
                walkTimeLeft = 1; // Ensure variable doesn't exceed 1     
            }
        }
        else
        {
            walkAniTime = 0;
            pState = PLAYER_ST.IDLE; // Change state back to idle         
        }
    break;
Any other ideas or is it something I'm missing.
 
So the problem is with the sprite? Where are you changing the sprite from walk to idle?
The problem is with movement itself. The animation is being changed the step event of the character object:
Code:
/// Animation Setting

// Pause and play out animation depending on whether the game was paused or not.
if global.gamePaused == false { image_speed = aniSpd; } else { image_speed = 0; }

// Automatically Switch between animations
switch( pState )
{
    case PLAYER_ST.IDLE:
        if sprite_index != charIdleSpr[ pDir ] { image_index = 0; sprite_index = charIdleSpr[ pDir ]; setAniSpd( sprite_index ); }      
    break;

    case PLAYER_ST.WALKING:
        if sprite_index != charWalkSpr[ pDir ] { image_index = 0; sprite_index = charWalkSpr[ pDir ]; setAniSpd( sprite_index ); }
      
    break;
  
    case PLAYER_ST.RUNNING:
  
  
    break;
  
    case PLAYER_ST.HURT:
  
    break;
  
    case PLAYER_ST.ATTACKING:
  
  
    break;
}
The code I posted before is from the character object's parent.
 

Bentley

Member
@TheNegroShoddy Edit: nevermind.

Hmm, I don't know man. The movement looks ok except for a stutter in between cells. I'm not sure tbh. Is the stutter b/c of the animation As @TheouAegis said. I didn't see any walk animation when I watched the video.

Sorry I can't be of more help.
 
Last edited:
@TheNegroShoddy Edit: nevermind.

Hmm, I don't know man. The movement looks ok except for a stutter in between cells. I'm not sure tbh. The logic I use is:

if (snapped)
set target x // If there's input
else
move to target x

So somewhere you must be going wrong. Sorry I can't be of more help.
Sorry I should've been more clear. Yeah I wanted to know how to fix that weird stutter with the movement, plus sometimes the character won't stop moving one direction even if I let the key go.
 
@TheNegroShoddy Edit: nevermind.

Is the stutter b/c of the animation As @TheouAegis said. I didn't see any walk animation when I watched the video.

Sorry I can't be of more help.
Oh I didn't see you edit your post again, well I don't have a walk animation yet, only two sprites I was given. Using one for the idle and one for the walking animation, although the difference is probably hard to tell. The animation code really shouldn't be affecting how movement is behaving cause the code is separate.
 
Last edited:
Top