Great, great video! The coding and explanation is perfect! One issue though that I found also that other viewers mention is that after many clicks the input is disabled. Its not fault of the code shown in the video nor you need to check the state of the enemy object. It's actualy how paths work in GMS2. Issue: After the path_start() function is triggered, even if the path_action is declared as path_action_end, path_speed will STILL have influence to the x and y of the enemy object, thus, making its x and y coordinates to decimals (like 31.99). This will mess up the mp_grid and the path wont re-calculate again the mp_grid_path(). Solutions: A) Easiest that I found (at least in my case) is, during the PathEnd Event, I set, before anything else, the path_speed = 0 and also re-calculate the x and y of the instance to snap to grid with this x = floor(x/global.cell_size) * global.cell_size; y = floor(y/global.cell_size) * global.cell_size; B) For better (a bit less optimal but more efficient solution) is to alway allign your enemy's coordinates with the x = floor(x/global.cell_size) * global.cell_size; y = floor(y/global.cell_size) * global.cell_size; during each step, this will fix the problem once and for all! I hope that helps! Again, great video keep up the good work!
Thanks man I just got here from hitting the limits of mp_potential_step & collision circles hopefully this works better I like that you included the draw events to see things in action and it felt like i learnt something compared to some other peoples tutorials where its just presto and its done
Amazing! Thanks so much, but just asking, how can you have a block object for example and place it in a room (Manually) and the code knows that the block is there, so the player/enemy avoids it automatically. (only when you create your own levels)? Thanks.
Great tutorial, thanks! I have a small issue in that the pathing completely breaks down if you double click or rapidly press the left mouse button - the pathing seems to get confused and sometimes disables input on the program. I fixed this with a simple if statement before the movement function though.
Hello my friend thank you so much for your always great work, can you make someday a video please, talking about how to create a pathfinding for platform games? I will thank you so much
Im not sure if this is how you intended, but when i click while the code is running, the path's get "added" together and the obj_enemy goes places it shouldn't. Is this intentional or some kind of bug because I wanted to make modifications where every time you click, moving or not, the path would always update to the new mousex and mousey position.
thank you! I make my own levels and I place the walls myself, how would I make it so that instead of randomizing the grid I can use the walls I've already placed down? thank you!!!!
Hi! You can place dynamicaly objects inside the grid with the mp_grid_add_instances() function. This will automaticaly place all instances of the desired object as obstacles inside the grid. Example Lets say you have a wall object called obj_wall. You can place them inside your room like you normaly would and change the randomized part of the script to this: mp_grid_add_instances(global.grid, obj_wall, true);
I did it this way (It's kind of clunky, but the best I could think up): 1. First, remove the impassable cell that the end of the path is colliding with from the mp_grid (using mp_grid_clear_cell) and run mp_grid_path again to get a valid path. You should then mark the cell as impassable again using mp_grid_cell_add 2. With this you can work out the coordinates of the second to last point on the path using path_get_point_x(your_path,path_get_number(your_path)-2) (do the same for path_get_point_y), and then use point_direction to calculate the angle between the end of the path and the second to last point on that path. 3. Using the angle you can use lengthdir_x & lengthdir_y(length, angle) to work out the coordinates of a point further back along the path where it's not going to hit the impassable wall. The length could be your mp_grid's cell size. *execute mp_grid_path again with these new x & y coordinates as the end coordinates for the path. Assuming no other impassable area on the grid is blocking the path, this should work. Like I said, this is clunky and there may be a better way, but this is what I came up with.
Nice, but you have a serious mistake there. In Event 2 is the use of function "place_meeting" mistake. Because object "obj_Grid_Init" will never meet "obj_Wall. "obj_Enemy" spawns under the object "obj_Wall. Use this instead: collision_rectangle(_position_x, _position_y, _position_x + 64, _position_y + 64, nopass_obj, false, true) == noone
Great, great video! The coding and explanation is perfect! One issue though that I found also that other viewers mention is that after many clicks the input is disabled. Its not fault of the code shown in the video nor you need to check the state of the enemy object. It's actualy how paths work in GMS2.
Issue: After the path_start() function is triggered, even if the path_action is declared as path_action_end, path_speed will STILL have influence to the x and y of the enemy object, thus, making its x and y coordinates to decimals (like 31.99). This will mess up the mp_grid and the path wont re-calculate again the mp_grid_path().
Solutions:
A) Easiest that I found (at least in my case) is, during the PathEnd Event, I set, before anything else, the path_speed = 0 and also re-calculate the x and y of the instance to snap to grid with this
x = floor(x/global.cell_size) * global.cell_size;
y = floor(y/global.cell_size) * global.cell_size;
B) For better (a bit less optimal but more efficient solution) is to alway allign your enemy's coordinates with the
x = floor(x/global.cell_size) * global.cell_size;
y = floor(y/global.cell_size) * global.cell_size;
during each step, this will fix the problem once and for all!
I hope that helps! Again, great video keep up the good work!
This is incredibly insightful and useful, thank you!
Thank you very much for a great tutorial! Its incredible the value of having these pathing tools available in our coding toolkit. Thanks again! :-)
Thank you so much! :)
Thanks man I just got here from hitting the limits of mp_potential_step & collision circles hopefully this works better I like that you included the draw events to see things in action and it felt like i learnt something compared to some other peoples tutorials where its just presto and its done
Thanks alot! i actually learned something!
lmao i didn't even know gamemaker had motion planning functions, great tutorial, saved me a lot of time making my own worse pathfinding algorithm haha
Thank you so much man!
this is extremely helpful, wow
Amazing! Thanks so much, but just asking, how can you have a block object for example and place it in a room (Manually) and the code knows that the block is there, so the player/enemy avoids it automatically. (only when you create your own levels)? Thanks.
Did you ever find out? Here's what I did:
under 'global.grid = mp_grid_create(); just put mp_grid_add_instances(global.grid, o_solid, 1);
@@DrJurdenPeterbergsteinlerwitz thanks
Thank you. This tutorial was helpful!
Great tutorial, thanks! I have a small issue in that the pathing completely breaks down if you double click or rapidly press the left mouse button - the pathing seems to get confused and sometimes disables input on the program. I fixed this with a simple if statement before the movement function though.
great tutorial
Hello my friend thank you so much for your always great work, can you make someday a video please, talking about how to create a pathfinding for platform games? I will thank you so much
Im not sure if this is how you intended, but when i click while the code is running, the path's get "added" together and the obj_enemy goes places it shouldn't. Is this intentional or some kind of bug because I wanted to make modifications where every time you click, moving or not, the path would always update to the new mousex and mousey position.
thank you! I make my own levels and I place the walls myself, how would I make it so that instead of randomizing the grid I can use the walls I've already placed down? thank you!!!!
Hi! You can place dynamicaly objects inside the grid with the mp_grid_add_instances() function. This will automaticaly place all instances of the desired object as obstacles inside the grid.
Example
Lets say you have a wall object called obj_wall. You can place them inside your room like you normaly would and change the randomized part of the script to this:
mp_grid_add_instances(global.grid, obj_wall, true);
How would I modify it so if I click a wall or other impassable cell, it finds the nearest empty cell and moves there instead?
I did it this way (It's kind of clunky, but the best I could think up):
1. First, remove the impassable cell that the end of the path is colliding with from the mp_grid (using mp_grid_clear_cell) and run mp_grid_path again to get a valid path. You should then mark the cell as impassable again using mp_grid_cell_add
2. With this you can work out the coordinates of the second to last point on the path using path_get_point_x(your_path,path_get_number(your_path)-2) (do the same for path_get_point_y), and then use point_direction to calculate the angle between the end of the path and the second to last point on that path.
3. Using the angle you can use lengthdir_x & lengthdir_y(length, angle) to work out the coordinates of a point further back along the path where it's not going to hit the impassable wall. The length could be your mp_grid's cell size.
*execute mp_grid_path again with these new x & y coordinates as the end coordinates for the path. Assuming no other impassable area on the grid is blocking the path, this should work.
Like I said, this is clunky and there may be a better way, but this is what I came up with.
Nice, but you have a serious mistake there. In Event 2 is the use of function "place_meeting" mistake. Because object "obj_Grid_Init" will never meet "obj_Wall.
"obj_Enemy" spawns under the object "obj_Wall.
Use this instead: collision_rectangle(_position_x, _position_y, _position_x + 64, _position_y + 64, nopass_obj, false, true) == noone
Whoops. Thanks for pointing that out, my bad
Great video very helpful I just have one question, how would you do for an 8 direction path finding?
Hi! A bit late haha but you can easily create 8direction path finding by allowing diagonals in mp_grid_path(). Hope that helps!
Thank you. This tutorial was helpful!