Ok, fine. Let's take a look at Blinky, the most basic ghost in Pac-Man. Since he is the most basic ghost, we will also make him the parent of all other ghosts.
In the Begin Step event, specify the target coordinates to move toward. In Blinky's case, the target coordinates are usually Pac-man's. When Pac-man is invincible, Blinky tries to run toward one of the corners, so we need to specify that. For Pac-Man's invincibility, I will use the global variable
global.PillPower. If the ghost is dead, I use the instance variable
goHome.
Code:
///Begin Step Event
if goHome {
targetX = //whatever the x-coordinate is for the ghost's home;
targetY = //whatever the y-coordinate is for the ghost's home;
speed = 4;
}
else
if global.PillPower {
targetX = 0;
targetY = 0;
speed = 4;
}
else {
targetX = obj_Player_1.x;
targetY = obj_Player_1.y;
speed = 4;
}
Note: I set speed like this here instead of the Create Event because technically the ghosts can move at different speeds depending on if they're fleeing or attacking. In your particular case, it likely doesn't matter where you set it.
Unlike Pac-man, Blinky can only change directions when he's in the middle of a junction -- ghosts cannot go backwards normally. This is actually good for the ghosts, since the player will be unable to trick them into a back-and-forth loop. Like Pac-man, we know Blinky is in the middle of a junction when (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0, assuming you centered the origin for Blinky's sprite. But again, unlike Pac-Man, we can't just worry about walls in the direction Blinky wants to move, but
all the walls around him so he can hopefully pick the best route toward his target. To do this, we need an array of all available directions excluding the path that is directly behind Blinky -- ghosts cannot go backwards normally.
After we have the array of viable paths filled out, we need to find the best path toward the target. If there is only one available path, we take that one, otherwise we need to deduce the best available path. To figure that out, we need to find the distance to the target. When moving along a grid, the distance to any point is abs(x1-x2)+abs(y1-y2). In most cases, we don't care about the total distance toward the target, we only need to worry about which distance -- horizontal or vertical -- is more significant. If the vertical distance was greater than the horizontal distance, the ghost would try to move vertically. If that desired path is unavailable, you try the next preferred path. So if Blinky wanted to move down and right but there was a wall below him, he would try to move right. If moving in the other direction is not an option, you randomly pick one of the available options.
Note: This method is a little different from the one I gave the other guy.
Code:
///Step Event
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
for(var paths, i=0; i<4; i++;)
paths[i] = -1;
var n = 0;
for(i=0; i<360; i+= 90;) {
if i != (direction + 180) mod 360
if !place_meeting(x+lengthdir_x(grid/2,i), y+lengthdir_y(grid/2,i), obj_Pac_Collision)
paths[n++] = i;
}
if paths[0] == -1 { //this should NEVER happen, but just in case...
direction = 270;
exit;
}
if paths[1] == -1 { //this means there is only one path available
direction = paths[0];
exit;
}
var h = abs(targetX - x);
var v = abs(targetY - y);
var dx = point_direction(x,y,targetX,y);
var dy = point_direction(x,y,x,targetY);
if h > v {
//Try to move horizontally
for(i=0; i<4; i++;)
if paths[i] == dx {
direction = dx;
exit;
}
for(i=0; i<4; i++;)
if paths[i] == dy {
direction = dy;
exit;;
}
}
else
if v > h {
//Try to move vertically
for(i=0; i<4; i++;)
if paths[i] == dy {
direction = dy;
exit;
}
for(i=0; i<4; i++;)
if paths[i] == dx {
direction = dx;
exit;
}
}
//If both distances are the same or both desired paths are unavailable, pick a random one
i = irandom(3);
while paths[i] == -1
i = ++i mod 4;
direction = paths[i];
}
Or if you would rather use a ds_list instead of an array, you could try the following.
Code:
///Create Event
paths = ds_list_create();
Code:
///Step Event
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
ds_list_clear(paths);
for(i=0; i<360; i+= 90;)
if i != (direction + 180) mod 360
&& !place_meeting(x+lengthdir_x(grid/2,i), y+lengthdir_y(grid/2,i), obj_Pac_Collision)
ds_list_add(paths,i);
if !ds_list_size(paths) { //this should NEVER happen, but just in case...
direction = 270;
exit;
}
if ds_list_size(paths) == 1 { //this means there is only one path available
direction = paths[|0];
exit;
}
var h = abs(targetX - x);
var v = abs(targetY - y);
var dx = point_direction(x,y,targetX,y);
var dy = point_direction(x,y,x,targetY);
if h > v {
//Try to move horizontally
if ds_list_find_index(paths, dx) > -1 {
direction = dx;
exit;
}
if ds_list_find_index(paths,dy) > -1 {
direction = dy;
exit;
}
}
else
if v > h {
//Try to move vertically
if ds_list_find_index(paths,dy) > -1 {
direction = dy;
exit;
}
if ds_list_find_index(paths,dx) > -1 {
direction = dx;
exit;
}
}
//If both distances are the same or both desired paths are unavailable, pick a random one
i = irandom(3) * 90;
while ds_list_find_index(paths,i) < 0
i = (i + 90) mod 360;
direction = i;
}