Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Pacman movement

This thread is locked; no one can reply to it. rss feed Print
Pacman movement
Steve Terry
Member #1,989
March 2002
avatar

I got pacman AI working pretty good with four ghosts moving along but at the moment I have it tile based meaning pacman and the ghosts don't move so smoothly. Instead of moving by 22 pixels each time I need him to move pixel by pixel which seemed fine since I would just plot him at absolute coordinates and figure out where he is on the map by dividing those coordinates by 22. Unfortunately it didn't work out so well because moving left he stops one tile before he should and he's moving inbetween tiles now which he shouldn't. I had the suggestion of using offsets to move between tiles but I want to know of other methods or something that may work. I have to constantly move pacman (even if the keyboard isn't pressed), he has to move at whole tiles only (can't move when inbetween tiles), and somehow I have to get his screen coordinates down to map coordinates. I had thought of leaving his coordinates the map coordinates and interpolating his movement... would this be easier, for intance if I have a delay of 20 for a 1/100s timer and I need to move him 22 pixels before that timer is up is that easy? Or should I stick with screen to map coordinates and instead of upper left take his coordinates from the midpoint? I didn't think moving pacman would be so difficult ???

        if(pacman.move_dir == PMAN_MOVE_RIGHT){
      if((pacman.x / 22) + 1 < 19 && map[pacman.y / 22][(pacman.x / 22) + 1] != '#'){
        pacman.x++;
                // Eat the dot
        map[pacman.y / 22][pacman.x / 22] = ' ';
      }
    }
    else if(pacman.move_dir == PMAN_MOVE_LEFT){
      if((pacman.x / 22) - 1 >= 0 && map[pacman.y / 22][(pacman.x / 22) - 1] != '#'){
        pacman.x--;
        map[pacman.y / 22][pacman.x / 22] = ' ';
      }
    }

Moving right seems to work just fine... moving left or up is a problem...

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Kanzure
Member #3,669
July 2003
avatar

What?!

If you are talking about 'animation' (pretty much non in pacman :P), then I suggest structering your game off of an RPG in the depot, uh, Saeurkrat(?). In the game, the engine allows entities to have a script, and the script says "moveTo(position)". The engine would move the thingy each time, and then once it reaches the destination (or some problem arises), it goes back to the script. Do something like this, I think it would still work without scripts :) Set a destination for the pacman, have your game move the pacman, and then when it's done moving, go back to whatever function for determining where to go. :)

I hope I made my confusion as posty as yours! Err...wait. :P

Edit: Beaten...by your edit.

Richard Phipps
Member #1,632
November 2001
avatar

Keep it as you have now, but you use pixel coords which you divide by tile width and height. Then only check for movement logic, etc.. when you cross a new tile boundary and get a new DX and DY to add to the pixel X and Y until another tile boundary has been crossed.

Steve Terry
Member #1,989
March 2002
avatar

Richard... ok I see so I move pacman but only when his screen coords:
(pacman.x % 22) == 0 && (pacman.y %22) == 0
then make adjustments to the map/allow for new input?

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Richard Phipps
Member #1,632
November 2001
avatar

Yes, you only need to check for changes in movement when your ghost is completely in a new tile. Just add DX and DY to the ghost's X and Y until a new tile is crossed:

dx = ghost[g].dx;
dy = ghost[g].dy;

if (x / TILE_W != (x + dx) / TILE_W || y / TILE_H != (y + dy) / TILE_H)
{
 // Do movement logic..
 // New dx and dy will be set directly in ghost[g] struct.
}
 x = x + dx;
 y = y + dy;

Krzysztof Kluczek
Member #4,191
January 2004
avatar

Maybe you could make it tile based with smooth movement?

1int pac_x,pac_y,pac_dir,pac_frame;
2 
3// logic update:
4if(pac_frame>0)
5{
6 pac_frame++;
7 if(pac_frame>=22)
8 pac_frame=0;
9}
10else
11{
12 pac_dir=NONE;
13 if(key[KEY_UP]) pac_dir=UP, pac_y--;
14 // etc. for other directions
15}
16 
17// drawing
18int xp=pac_x*22, yp=pac_y*22;
19if(pac_dir==UP) yp-=pac_frame;
20if(pac_dir==DOWN) yp+=pac_frame;
21// etc.

This way Pac-Man moves smoothly, but can stop only at tiles, which should be simple enough and good enough. :)

Richard Phipps
Member #1,632
November 2001
avatar

(pacman.x % 22) == 0 && (pacman.y %22) == 0
Although this seems more elegant than the way I check for tile boundaries, the problem with this approach is it won't be able to cope with any skipped logic frames if you use a timer system.

Although I doubt this would occur.. I'm not 100% sure it wouldn't.

Krzysztof Kluczek
Member #4,191
January 2004
avatar

while(my_timer>0)
{
  do_logic();
  my_timer--;
}

If he does logic timing this way that won't be any problem (that's what I'm always doing - at least I'm sure everything works always the same). :)

Richard Phipps
Member #1,632
November 2001
avatar

I think you are right, but I am not 100% sure as I said. :-/

Krzysztof Kluczek
Member #4,191
January 2004
avatar

It will only fail if logic moved Pac-Man more than one pixel at time or drawing routines would change Pac-Man's position. There are no skipped logic frames, only delayed ones, and even if you skipped some do_logic() calls it still runs fine but lags a bit since do_logic() should be the only function to change Pac-Man's position. :)

Richard Phipps
Member #1,632
November 2001
avatar

I would still use the check I posted because otherwise Pacman has to move at either 1 or 2 pixels per frame (and I think 4 pixels per frame at least would be required). Any greater and the check will be missed. Plus the method I posted will let you add speed powerups and things like that if you want to at a later date.

EDIT: You could of course put the movement in another loop inside each logic loop. But then it starts to look messy.

Go to: