• 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 mp_grid movement question [Solved]

PlayerOne

Member
When using an mp_grid in conjunction with a path is there a way to make a path have a strict 4 way movement pattern?

For example: In my current project (image attached) the current path being drawn (shown in pink) has the object following a path at a slight angle. There are other movement instances similar to this and my overall goal here is to just have my enemy objects follow a strict 4 way movement within the mp_grid.

I looked through the docs for anything to go on, disabled the vertical movement, and I'm left scratching my head as to how to fix this.
 

Attachments

NightFrost

Member
Short answer: nothing you can do in settings. Paths always want to align you to the centers of grid cells, and if you're not there already, they'll bring you there. I suppose you could avoid that by doing pathfinding only when exactly aligned to grid.
 

PlayerOne

Member
Short answer: nothing you can do in settings. Paths always want to align you to the centers of grid cells, and if you're not there already, they'll bring you there. I suppose you could avoid that by doing pathfinding only when exactly aligned to grid.
Any tutorial or post you can recommend that would snap an object to a grid while in motion?
 
As Nightfrost said - paths go from the center of the cell. So if you build a path from your x / y position, and it's not centered, then it results in a path line that isn't straight when it goes to the first cell where it can hit the center.

I think if your cells are 32 by 32, and your sprites have a centered origin, you'd use something like:

if ((x mod 16 == 0) && (y mod 16 == 0) && (x mod 32 != 0) && (y mod 32 != 0))
{is in center}
else
{figure out nearest center point, and snap to it before path building}

The middle of cell zero would be 16 / 16. So, if I've figured this correctly, as long as division by 16 results in zero (nothing left over after using mod), and division by 32 results in something left over, then you'd know its not a multiple of 32 (16 times two etc).
If all four of these conditions were equal to zero, then it's x / y position would be equal to one of the corners of a cell (32 / 32)
 

NightFrost

Member
If you want your enemies to stick to the grid while moving (and only move N/E/S/W) have them start at centers of the cells. Have them recalculate their paths (if necessary) only when they have either reached a node in a path, which will be in center of a cell, or if moving randomly, when they have reached center of a cell. This will introduce some lag to directional switches as they have to move to centers first, but they won't ever move diagonally as there will be no need to.
 

PlayerOne

Member
As Nightfrost said - paths go from the center of the cell. So if you build a path from your x / y position, and it's not centered, then it results in a path line that isn't straight when it goes to the first cell where it can hit the center.

I think if your cells are 32 by 32, and your sprites have a centered origin, you'd use something like:

if ((x mod 16 == 0) && (y mod 16 == 0) && (x mod 32 != 0) && (y mod 32 != 0))
{is in center}
else
{figure out nearest center point, and snap to it before path building}

The middle of cell zero would be 16 / 16. So, if I've figured this correctly, as long as division by 16 results in zero (nothing left over after using mod), and division by 32 results in something left over, then you'd know its not a multiple of 32 (16 times two etc).
If all four of these conditions were equal to zero, then it's x / y position would be equal to one of the corners of a cell (32 / 32)
Your code works to a degree. Now I know I'm screwing up somewhere because the way the enemies move in the grid only follows the players position at the start of the room. When that enemy hits the position it will either stop or continue depending on a few factors when the player moves.

Code:
var start_x = argument0
var start_y = argument1
var end_x = argument2
var end_y = argument3
var _speed = argument4
var _endaction = argument5

   path=path_add()
   if ((x mod 32 == 0) && (y mod 32 == 0) && (x mod 64 != 0) && (y mod 64 != 0))
   {     
       mp_grid_path(global.battle_grid,path,start_x,start_y,end_x,end_y,false)
       path_start(path,_speed,_endaction,false)
   }
The movement is solid (L,R,U.D), the path-finding goes haywire and will either stop or continue but will stop permanently when meeting the player.
 
That code will only tell you if it's in the middle of a cell. If it's in the middle of a cell, and you build a path, it should remove any diagonal movements. I'm assuming you have not set 'diagonal' to true when making the path, and that it is making diagonal movements due to the starting position not being dead center of the cell the object is in. That would seem to be the case in the picture you included.

But the way you have it set up now - it will only build a path when it is in the middle of a cell. And it will only build another path after that if the end destination of the previous path was in the middle of a cell. At a rough guess:

1) The end point of the previous path is not meeting the conditions imposed on it. If it is heading towards the player, and the players x / y position is not in the middle of a cell, then when it reaches the end and tries to build a new path - it can't.

2) If it has moved along the path, and then tries to build a new path before reaching the end (i.e what should be the middle of a cell) - it won't be able to. Because it's not necessarily in the middle of a cell when it's trying to build a new path

This is what I put:

if ((x mod 16 == 0) && (y mod 16 == 0) && (x mod 32 != 0) && (y mod 32 != 0))
{is in center} // can build path without any diagonal movement - at least to the next cell
else
{figure out nearest center point, and snap to it before path building} <<<<<<<< this is the bit you've missed doing

You've totally limited the conditions under which it can make paths. Whereas what I intended for you to understand was that those are the conditions you want to have met BEFORE making a path.
 

PlayerOne

Member
That code will only tell you if it's in the middle of a cell. If it's in the middle of a cell, and you build a path, it should remove any diagonal movements. I'm assuming you have not set 'diagonal' to true when making the path, and that it is making diagonal movements due to the starting position not being dead center of the cell the object is in. That would seem to be the case in the picture you included.

But the way you have it set up now - it will only build a path when it is in the middle of a cell. And it will only build another path after that if the end destination of the previous path was in the middle of a cell. At a rough guess:

1) The end point of the previous path is not meeting the conditions imposed on it. If it is heading towards the player, and the players x / y position is not in the middle of a cell, then when it reaches the end and tries to build a new path - it can't.

2) If it has moved along the path, and then tries to build a new path before reaching the end (i.e what should be the middle of a cell) - it won't be able to. Because it's not necessarily in the middle of a cell when it's trying to build a new path

This is what I put:

if ((x mod 16 == 0) && (y mod 16 == 0) && (x mod 32 != 0) && (y mod 32 != 0))
{is in center} // can build path without any diagonal movement - at least to the next cell
else
{figure out nearest center point, and snap to it before path building} <<<<<<<< this is the bit you've missed doing

You've totally limited the conditions under which it can make paths. Whereas what I intended for you to understand was that those are the conditions you want to have met BEFORE making a path.

I see where I went wrong - I think. After some tinkering the path finding will now just follow the path to the players last known position and continue from that point. Thank you for the help. I do mean it you have helped me alot with getting this Ai off the ground.

Code:
     if ((x mod (64/2) == 0) && (y mod (64/2) == 0) && (x mod 64 != 0) && (y mod 64 != 0))
       {           
          if (mp_grid_path(global.battle_grid, path, x, y, _xx, _yy, false))
          {       
          path_start(path, spd, 0, 0);
          }
   }
 
Top