Pac-Man Movements

OK so I almost got the Pac-Man movement down I just need a lil help with him moving into new junctions. Does anyone know how to only have Pac-Man move to a selected direction without going into the wall, like a wall detection code or specific movement code? much appreciated it you do.
 

TheouAegis

Member
When Pac starts, set his hspeed to move left. If the player presses a direction, check if it is the opposite direction Pac is already moving. If it is, reverse Pac's direction. If it's not, save the direction the player is trying to move to a variable. If Pac's coordinates are in the middle of a junction (typically when his left and top bounds are aligned to a grid), then check if there is no wall in the direction you saved. If there isn't, move Pac in that direction. Save Pac's current direction to that variable, even if you don't change directions. If there is a wall on Pac's direction of movement, stop him completely and snap him so his top and left bounds are aligned to the grid so when the player moves him again, he will be able to change direction.
 

TheouAegis

Member
Really, you could set it to whatever you want, but the original Pac-Man starts each round moving left. I guess I should have just said, "set Pac-man's hspeed so he starts moving on his own".
 
OK I see what you mean, and what the outcome is that when it started it didn't go start off going left, it didn't move at all until i hit a key.
 
if (keyboard_check_pressed(vk_left)){
direction = 180;

hspeed = +hspeed;

sprite_index = Pac_Man_left;
image_index += 0;

image_speed = 1;
}
if (keyboard_check_pressed(vk_up)){
direction = 90;

speed = spd;

sprite_index = Pac_Man_up;
image_index += 0;

image_speed = 1;

}
if (keyboard_check_pressed(vk_right)){
direction = 0;

speed = spd;

sprite_index = Pac_Man_right;
image_index += 0;

image_speed = 1;
}
if (keyboard_check_pressed(vk_down)){
direction = 270;

speed = spd;

sprite_index = Pac_Man_down;
image_index += 0;

image_speed = 1;
}
move_wrap(true, true, 1);
 

TheouAegis

Member
Yeah, it's gonna take some work and I've been busy with Halloween. lol

Change this back to speed=spd:
hspeed = +hspeed

to make Pac-Man start moving left or any direction for that matter as beginning of the game, set his speed and direction i(and sprite) in his create event.

Now, are you using drag-and-drop, or are you using gml? If you are using gml, you can delete all of these:
image_index += 0;

To prevent him going into walls, since you are using speed here, use a collision event.
Collision Event with obj_wall:
Code:
x =xprevious;
y =yprevious;
var h= sign(hspeed), v = sign(vspeed);
speed = 0;
image_speed = 0;
while !place_meeting(x+h,y+v, obj_wall) {
    x+=h;
    y+=v;
}
Get that to work, and then we can go into the rest of the flaws in your Pac-Man code. What you have is the basics, so once you get the basics down, you can move on to the more advanced, technically stuff.
 
OK so I put the code in (though had to change obj_wall into the name of the collision i had set for the wall) and he's still able to turn into them. Is there a specific way to putting the code in? Btw I am using GML.
 

TheouAegis

Member
He can turn into them... But does he at least stop if he runs into one normally?

Your walls aren't marked as solid, are they? If they are, xprevious and yprevious shouldn't be needed.

Is that the full code for Pac-Man or do you have other code in him that you are not showing? I mean, other than the collision event now. You should post ALL the code currently in Pac-man. Don't leave anything out.

Also make sure your sprites for Pac-man all have the same origin and same bounding box size.
 
This all the codes I have for Pac-Man before the help.

Create:

image_index = 0;

image_speed = 0;

spd = 4;

grid = 32;

Step:
hspeed = +hspeed;

if (keyboard_check_pressed(vk_left)){
direction = 180;

speed = spd;
sprite_index = Pac_Man_left;
image_speed = 1;
}
if (keyboard_check_pressed(vk_up)){
direction = 90;
speed = spd;
sprite_index = Pac_Man_up;
image_speed = 1;
}
if (keyboard_check_pressed(vk_right)){
direction = 0;
speed = spd;
sprite_index = Pac_Man_right;
image_speed = 1;
}
if (keyboard_check_pressed(vk_down)){
direction = 270;
speed = spd;
sprite_index = Pac_Man_down;
image_speed = 1;
}
move_wrap(true, true, 1);

Collision:
speed = 0;

image_speed = 0;

image_index = 0;
 

TheouAegis

Member
Remove hspeed=+hspeed. It's wrong.

If the wall object is not solid, then you need to keep the x=xprevious and y=yprevious. When using speed/direction, Pac-Man will move on his own at the end of the Step event, so collisions happen after that movement but before the End Step event. What this also means is unless you actually mark the walls as solid, which automatically puts Pac-Man at his old position, you need to move Pac-Man back to his old position because he is already inside a collision by the time the event fires. if Pac-Man is in a collision and not moved out of the collision, then he will continue to walk through walls.
 
Oh no I think you might've mistook me asking help bout him going through walls. The wall collision is working just fine regarding stopping him from going through, the problem was that I'm trying to figure out how to get him to turn in a junction without him automatically hitting a wall when ever I hit said key before hitting said junction.
 

TheouAegis

Member
Oh okay good. Because that was the "flaw" I was mentioning a few posts up.

This is going to be brief, because I'm on my way to work and can't really go into much detail just now. Basically, you see how your code makes Pac-Man move as soon as you press the key? Yeah, it doesn't work like that. When the player pressed the key, emphasis on the word pressed, store that desire direction associated with that key in a variable. Then check if that direction is the opposite direction in which Pac-Man is already going. If it is, change Pac-Man's direction right there. Now, what you need to add is a check for when Pac-Man reaches the middle of a junction. Classically, you check if his coordinates minus half the grid size are aligned with the grid (e.g. if (x-grid/2) mod grid == 0 && (y-grid/2) mod grid == 0). This is why in another post I had said to make sure your speed at which you move is evenly divisible by the size of the grid, which you are doing here. So then when that condition is met, you check if the desired direction what you saved is clear of any walls. If it is, you set a commands direction; otherwise you make Pac-Man stop because the player picked a wrong direction.
 
OK so basically the code should look like "if (x-grid/4) mod grid == 0 && (y-grid/4) mod gird == 0 since" since my move speed is 4 and grid size is 32 right?
 

TheouAegis

Member
Step. Basic oder should be like
Code:
if keyboard_check_pressed(vk_right) new_dir=0;
else if keyboard_check_pressed(vk_left) new_dir=180;
else if keyboard_check_pressed(vk_up) new_dir=90;
else if keyboard_check_pressed(vk_down) new_dir=270;
if direction == (new_dir + 180) mod 360 {
    direction = new_dir;
    switch direction {
        case 0: sprite_index = Pac_man_right; break;
        //repeat for other directions
    }
}
else  {
    if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
        var h = lengthdir_x(grid/2, new_dir);
        var v = lengthdir_y(grid/2, new_dir);
        if place_meeting(x+h,y+v,Wall) //or whatever your wall object is
            new_dir = direction; //this makes Pac-Man keep doing what he's doing
        else {
             direction = new_dir;
             //change sprite here, like before
        }
    }
}
 
It's saying there's a code error.
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Step Event0
for object obj_Player_1:
Variable obj_Player_1.new_dir(100004, -2147483648) not set before reading it.
at gml_Object_obj_Player_1_Step_0 (line 5) - if direction == (new_dir + 180) mod 360 {
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_obj_Player_1_Step_0 (line 5)
 
OK that fixed that problem question when you said to repeat for all directions did you mean repeat code starting at line 5 to line 11 or line 5 all the way to the rest of the code?
 

TheouAegis

Member
I just didn't want to write out that switch. Basically, it's just the switch for setting the Sprite. And where it says at the bottom "change Sprite here", it's the same thing.
 
Never mind I found a work around but the code isn't working still. Even the sprite image not changing as I pick a direction, or animating for that matter. I must not being putting the code in correctly
 

TheouAegis

Member
Always post updated code.

The collision event only has speed=0; image_speed=0; x=xprevious; y=yprevious.

The perfect collision loop I originally used isn't necessary since your grid size is a multiple of your speed, so this is all that's really needed in the collision.

Create event should have
Code:
direction = 180;
new_dir = direction:
sprite_index = Pac_man_left;
image_speed = 1;
speed = 4;
Everything else is Step.
 
OK this what I got now for his step and Create code:

Step

if keyboard_check_pressed(vk_right) new_dir=0;
else if keyboard_check_pressed(vk_left) new_dir=180;
else if keyboard_check_pressed(vk_up) new_dir=90;
else if keyboard_check_pressed(vk_down) new_dir=270;
if direction == (new_dir + 0) mod 360 {
direction = new_dir;
switch direction {
case 0: sprite_index = Pac_Man_right; break;
//repeat for other directions
}
}
else {
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
var h = lengthdir_x(grid/2, new_dir);
var v = lengthdir_y(grid/2, new_dir);
if place_meeting(x+h,y+v,obj_Pac_Collision) //or whatever your wall object is
new_dir = direction; //this makes Pac-Man keep doing what he's doing
else {
direction = new_dir;
//change sprite here, like before
}
}
}
if direction == (new_dir + 180) mod 360 {
direction = new_dir;
switch direction {
case 180: sprite_index = Pac_Man_left; break;
//repeat for other directions
}
}
else {
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
var h = lengthdir_x(grid/2, new_dir);
var v = lengthdir_y(grid/2, new_dir);
if place_meeting(x+h,y+v,obj_Pac_Collision) //or whatever your wall object is
new_dir = direction; //this makes Pac-Man keep doing what he's doing
else {
direction = new_dir;
//change sprite here, like before
}
}
}
if direction == (new_dir + 90) mod 360 {
direction = new_dir;
switch direction {
case 90: sprite_index = Pac_Man_up; break;
//repeat for other directions
}
}
else {
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
var h = lengthdir_x(grid/2, new_dir);
var v = lengthdir_y(grid/2, new_dir);
if place_meeting(x+h,y+v,obj_Pac_Collision) //or whatever your wall object is
new_dir = direction; //this makes Pac-Man keep doing what he's doing
else {
direction = new_dir;
//change sprite here, like before
}
}
}
if direction == (new_dir + 270) mod 360 {
direction = new_dir;
switch direction {
case 270: sprite_index = Pac_Man_down; break;
//repeat for other directions
}
}
else {
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
var h = lengthdir_x(grid/2, new_dir);
var v = lengthdir_y(grid/2, new_dir);
if place_meeting(x+h,y+v,obj_Pac_Collision) //or whatever your wall object is
new_dir = direction; //this makes Pac-Man keep doing what he's doing
else {
direction = new_dir;
//change sprite here, like before
}
}
}
move_wrap(true, true, 1);

Create

direction = 180;
new_dir = direction;
sprite_index = Pac_Man_left;
image_speed = 1;
speed = 4;
grid = 32;

Now the problem is he gets stuck when colliding with wall. I've tried the place_free code but it doesn't seem to work properly for me. I also tried to use place_snapped too but that doesn't work well either.
 
Last edited:

TheouAegis

Member
if direction == (new_dir + 0) mod 360 {
That needs to be +180 at all times.

Code:
if keyboard_check_pressed(vk_right) new_dir=0;
else if keyboard_check_pressed(vk_left) new_dir=180;
else if keyboard_check_pressed(vk_up) new_dir=90;
else if keyboard_check_pressed(vk_down) new_dir=270;
if direction == (new_dir + 180) mod 360 {
    direction = new_dir;
    speed = 4;
    image_speed = 1;
    switch direction {
        case 0: sprite_index = Pac_Man_right; break;
        case 90: sprite_index = Pac_Man_up; break;
        case 180: sprite_index = Pac_Man_left; break;
        case 270: sprite_index = Pac_Man_down; break;
    }
}
else
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
    var h = lengthdir_x(grid/2, new_dir);
    var v = lengthdir_y(grid/2, new_dir);
    if place_meeting(x+h,y+v,obj_Pac_Collision)
        new_dir = direction;
    else {
        direction = new_dir;
        speed = 4;
        image_speed = 1;
        switch direction {
            case 0: sprite_index = Pac_Man_right; break;
            case 90: sprite_index = Pac_Man_up; break;
            case 180: sprite_index = Pac_Man_left; break;
            case 270: sprite_index = Pac_Man_down; break;
        }
    }
}
move_wrap(1,1);
 
OK so I think progress is being made, now to get unstuck. I tried to press the up up key to move up but he still gets stuck on walls. Before you helping me I tried to use place_free and place_snapped but they didn't work properly for me. Any tips on how to get it to work properly?
 

TheouAegis

Member
Check your sprite origins. Make sure they are all centered. You want the center of Pac-man to be in the center of the grid when changing directions, so center his origin.
 

TheouAegis

Member
All tour Pac-man sprites are 96x96 in size? You should crop out all that empty space. But even if you leave the empty space in, set the bounds for each Pac-man sprite to:

left: 32
right: 63
top: 32
bottom: 63

Odds are your bounding box is too large.
 
OK I'm finally back after having no internet for almost a week. Also I finally got the collision mask in the right spots and now he's able to move freely through the maze (for the most part). Now the problem is that whenever he wraps from one side of the room to the other he gets unsnapped from the grid and the only way he can snapped back on is when I go back the direction he came from. How do I fix that?
 

TheouAegis

Member
Hm. That's an odd one. Do you mean he moves left off-screen, warps over to the right, and keeps moving left forever? Or do you mean as soon as he warps to the right he can move up or down immediately?
 

TheouAegis

Member
Set your move_wrap to either 4 (your speed) or GRID/2 instead of 1.

move_wrap(4,4)

That's the only thing I can think of. Give that a shot
 
OK so more question regarding the movement, Is there a better way to make turning more like the original because whenever I'm about to turn into a new direction I basically have to press said key at the exact or 1 space away free spot rather then holding said key to turn automatically to selected direction?
 

TheouAegis

Member
It shouldn't be... The new_dir variable is meant to store the direction the player pressed and then wait until Pac-Man reaches a junction.
 
well it's not really storing it, it's more so ignoring the command. I've havent really changed the code once you sent it to me

Step

if keyboard_check_pressed(vk_right) new_dir=0;
else if keyboard_check_pressed(vk_left) new_dir=180;
else if keyboard_check_pressed(vk_up) new_dir=90;
else if keyboard_check_pressed(vk_down) new_dir=270;
if direction == (new_dir + 180) mod 360 {
direction = new_dir;
speed = 4;
image_speed = 1;
switch direction {
case 0: sprite_index = Test_Player; break;
case 90: sprite_index = Test_Player; break;
case 180: sprite_index = Test_Player; break;
case 270: sprite_index = Test_Player; break;
}
}
else
if (x - grid/2) mod grid == 0 && (y-grid/2) mod grid == 0 {
var h = lengthdir_x(grid/2, new_dir);
var v = lengthdir_y(grid/2, new_dir);
if place_meeting(x+h,y+v,obj_Pac_Collision)
new_dir = direction;
else {
direction = new_dir;
speed = 4;
image_speed = 1;
switch direction {
case 0: sprite_index = Test_Player; break;
case 90: sprite_index = Test_Player; break;
case 180: sprite_index = Test_Player; break;
case 270: sprite_index = Test_Player; break;
}
}
}
move_wrap(true, true, 2);
 

TheouAegis

Member
Two things:

If it seems like new_dir is getting ignored, then these lines are at fault:
Code:
if place_meeting(x+h,y+v,obj_Pac_Collision)
new_dir = direction;
else
However, it's those lines that prevent Pac-Man from immediately stopping because there's a wall where he's trying to get to. So you can try removing those lines from the code, but I can guarantee you the whole thing will fall apart at that point.

The second thing is you could try reducing your speed from 4 to 2 or even 1. With your current setup of a great size of 32 and a speed of 4, if your room speed we're set to 60 which is standard, you have a split second to change direction. So if you reduce your speed drastically, you should see the code working properly.

You can always verify the code even works, to an extent. Print out the values of new_dir and direction in the GUI. Set your room speed to something low so you actually have time to look at the variables. (keep in mind though that if the roast beet is low, the keyboard is less responsive so you will need to hold keys down longer probably).
Code:
draw_text(0,0,string(direction)+"#"+string(new_dir));
room_speed = 5;
 

TheouAegis

Member
It means new_dir is set to right and direction is set to right. And apparently # doesn't work in your version for next line (lol).

You need to play the game a bit and make sure when you press a key to change direction that the 2nd number changes while the first one stays the same. The first number should only equal the second one at the start of the game and when you reach an intersection (or you try to move backwards).
 

TheouAegis

Member
the numbers not changing at all
Wait, are you saying it shows "0#0"all the time ? Because that first number should at least be changing, otherwise Pac-Man wouldn't be moving at all and you said Pac-Man was able to move and change directions, just not easily.. You put the code inside the Pac-Man object's Draw GUI event?

are you still using the Pac-Man object or are you using the test object on accident again?
 
Top