Pacman movement code
by Gary Preston · in Torque Game Builder · 03/14/2005 (8:13 am) · 20 replies
I'm currently implementing a simple pacman style game to help learn more about t2d. I've just updated the movement code for the pacman, and although it works, I'm not really happy with the results. I think the reason the movement code is causing me a few problems is that I'm trying to make it exact tile to tile movement, always ending at the center of the next tile.
I'm after a bit of advice on how I can re-implement the movement in a better way. It's kinda hard to explain how I've done it at the moment so I'd like to just upload my code onto my webserver for any of you who fancy giving me some pointers to download.
Due to the eula I can't make the code publically available but, would it be acceptable if I uploaded my full code to a secure passworded directory and posted the username/password and link to the code in this forum only? If not I can just upload my player.cs file, but its hard to see what the problem is without trying the thing out :P
I'm after a bit of advice on how I can re-implement the movement in a better way. It's kinda hard to explain how I've done it at the moment so I'd like to just upload my code onto my webserver for any of you who fancy giving me some pointers to download.
Due to the eula I can't make the code publically available but, would it be acceptable if I uploaded my full code to a secure passworded directory and posted the username/password and link to the code in this forum only? If not I can just upload my player.cs file, but its hard to see what the problem is without trying the thing out :P
#2
Hitting end walls isn't a problem, its when your travelling in one direction and could continue on for another few tiles, but want to turn into a gap thats coming up.
03/14/2005 (9:54 am)
Thats what I initially tried, but unless you end near the center of a tile it makes it difficult to move through a gap in the wall without colliding. Unless I make the collision box quite small, then you get a partial overwrap with the walls.Hitting end walls isn't a problem, its when your travelling in one direction and could continue on for another few tiles, but want to turn into a gap thats coming up.
#3
remember the collision doesn't need to be a box (don't mean to imply that you don't already know this)... you can have many sides, as long as its convex
03/14/2005 (9:59 am)
Recreating old classics and modifying them a bit is a great way to learn T2D... plus its fun :)remember the collision doesn't need to be a box (don't mean to imply that you don't already know this)... you can have many sides, as long as its convex
#4
That being said, I think I would probably start with using linear velocity to move him, but would probably end up with absolute positioning. If you remember, the character motion was very jerky, at least in the first versions of the game. If you're trying to reproduce that look, the slick T2D physics system would probably get in your way :-)
I found a .wav file of the "whakka-whakka" sound a couple of days ago. If I can dig it up, I'll send you a copy :-)
03/14/2005 (10:14 am)
Since Pacman can't stop moving (except when head-banging) all that is needed is a check to see if the direction being requested is valid. If not, the direction change request can be ignored. That way you can hold the "joystick" in the direction you want to go next, and he will continue in the current direction until it's possible.That being said, I think I would probably start with using linear velocity to move him, but would probably end up with absolute positioning. If you remember, the character motion was very jerky, at least in the first versions of the game. If you're trying to reproduce that look, the slick T2D physics system would probably get in your way :-)
I found a .wav file of the "whakka-whakka" sound a couple of days ago. If I can dig it up, I'll send you a copy :-)
#5
If the bounding box/sprite is almost the same size as a tile, it would be quite frustrating trying to get the pacman to fit in the gap, since his x velocity may move him passed the correct position. If I make the collision box smaller so that this isn't an issue, we then get a problem with the pacmans sides overlapping walls if you go two close to them.
Am I just going about this the wrong way? Basic movement left/right and stopping on collision is fine, so if moving up or down after you've hit a wall and stopped. Its the transition between a movement in one axis to a movement in the other through a single tile gap that seems to be the problem for me.
03/14/2005 (10:30 am)
Terry: Assuming you are travelling left, and press up to change direction, also assume the tile above the tile you have just entered is clear. The up might still fail if you are not fully within the center of the tile, since your right side of the collision box migth collide with the right wall of the gap your about to enter. Obviously both sides wouldn't collide as the box I'm using is less than the size of a tile, but it is possible for one side to collide.If the bounding box/sprite is almost the same size as a tile, it would be quite frustrating trying to get the pacman to fit in the gap, since his x velocity may move him passed the correct position. If I make the collision box smaller so that this isn't an issue, we then get a problem with the pacmans sides overlapping walls if you go two close to them.
Am I just going about this the wrong way? Basic movement left/right and stopping on collision is fine, so if moving up or down after you've hit a wall and stopped. Its the transition between a movement in one axis to a movement in the other through a single tile gap that seems to be the problem for me.
#6
The last time I saw PacMan code was in assembly on a 6502 processor, so my memory is probably more fuzz than fact, but I believe the motion controller was driven from a simple 2D array of bytes. Each element was one space of movement. I think there were 5 spaces between point dots, but I could be off. Each byte had bits which indicated allowed direction of travel, bits for prizes, and bits for enemies. You could probably splurge and use 16 bits, though, since I can't for the life of me figure out how to pack all of that into 8 bits :-)
Anyway, it could probably be done easily in T2D by using tiles for each movement point.
Here's a hideously bad drawing of it. The brackets represent a tile:
[.]
[]
[]
[ ] [] [] []
[.^>] [<>] [<>] [<>] [<>.] [<>] [<>] [<>] [<>.] [<>] [<>] [<>] [<^>.] [<>]
The dots are point dots, the arrows are travel indicators.
Pacman would move one tile for each time unit (using schedule() ?) and could only turn on tiles with the appropriate directions set.
If a ghost is on a tile, it sets a bit as well. Heck make it a whole boolean. We've got Gigs of RAM now :-) It clears the bit when it moves, and if the player is on a tile with the bit set, kaboom.
I hope there's a little sanity distillable from this. I may have dug too deep into the past, though, because I have this craving all of a sudden to go buy a Member's Only jacket :-)
03/14/2005 (11:20 am)
It would be difficult using the collision system, especially for the points you are mentioning. It's probably also overkill :-)The last time I saw PacMan code was in assembly on a 6502 processor, so my memory is probably more fuzz than fact, but I believe the motion controller was driven from a simple 2D array of bytes. Each element was one space of movement. I think there were 5 spaces between point dots, but I could be off. Each byte had bits which indicated allowed direction of travel, bits for prizes, and bits for enemies. You could probably splurge and use 16 bits, though, since I can't for the life of me figure out how to pack all of that into 8 bits :-)
Anyway, it could probably be done easily in T2D by using tiles for each movement point.
Here's a hideously bad drawing of it. The brackets represent a tile:
[.]
[]
[]
[ ] [] [] []
[.^>] [<>] [<>] [<>] [<>.] [<>] [<>] [<>] [<>.] [<>] [<>] [<>] [<^>.] [<>]
The dots are point dots, the arrows are travel indicators.
Pacman would move one tile for each time unit (using schedule() ?) and could only turn on tiles with the appropriate directions set.
If a ghost is on a tile, it sets a bit as well. Heck make it a whole boolean. We've got Gigs of RAM now :-) It clears the bit when it moves, and if the player is on a tile with the bit set, kaboom.
I hope there's a little sanity distillable from this. I may have dug too deep into the past, though, because I have this craving all of a sudden to go buy a Member's Only jacket :-)
#7
They hit up. If they can go up without collision, do so. If not set a flag for "move up if able" As long as they don't hit another direction key leave it. If they suddenly hit down, wipe all other "if able" flags and set down (assuming they can't move down right now). Then however often you feel necessary (might need frame I dunno) check again. As long as you do your linear velocity right based on the sizes of the sprite vs the area he has to squeeze into it should work.
Actually amend that slightly, I'd make the area he had to squeeze into exact, but with the check code I mentioned above it shouldn't be an issue.
Mind I'm still learning TorqueScript so I may be missing some issue with my version =-)
03/14/2005 (11:27 am)
Personally for movement I'd use something along the lines of the following.They hit up. If they can go up without collision, do so. If not set a flag for "move up if able" As long as they don't hit another direction key leave it. If they suddenly hit down, wipe all other "if able" flags and set down (assuming they can't move down right now). Then however often you feel necessary (might need frame I dunno) check again. As long as you do your linear velocity right based on the sizes of the sprite vs the area he has to squeeze into it should work.
Actually amend that slightly, I'd make the area he had to squeeze into exact, but with the check code I mentioned above it shouldn't be an issue.
Mind I'm still learning TorqueScript so I may be missing some issue with my version =-)
#8
For example lets say I know from the current position to the next tile position is 0.78 world units. Is there a way to specify that the sprite should move from the current position at a velocity of 15 and stop after 0.78 units? Is there a way I could cheat to achieve this if not?
One method I have tried is using the mount option to mount the player to the tile layer (which doesn't scroll :P) so that he ends up exactly at the position specified, but I then lose control of the velocity, only having control over the send to force.
Patrick: That is one thing I've tried, but depending on the velocity of the sprite and the size of the collision box compared to size of the wall openings, its very easy for the player to overshoot the point where they'd be able to move up. Unless I move the checks to on sceneupdate, that might resolve it.
03/14/2005 (11:38 am)
Terry: With that solution, wouldn't that still require been able to move to a precise location?For example lets say I know from the current position to the next tile position is 0.78 world units. Is there a way to specify that the sprite should move from the current position at a velocity of 15 and stop after 0.78 units? Is there a way I could cheat to achieve this if not?
One method I have tried is using the mount option to mount the player to the tile layer (which doesn't scroll :P) so that he ends up exactly at the position specified, but I then lose control of the velocity, only having control over the send to force.
Patrick: That is one thing I've tried, but depending on the velocity of the sprite and the size of the collision box compared to size of the wall openings, its very easy for the player to overshoot the point where they'd be able to move up. Unless I move the checks to on sceneupdate, that might resolve it.
#9
Damn it my first oldschool game was going to be pong but now I'm pondering this issue =-P
03/14/2005 (11:46 am)
Yeah you'd have to make sure your velocity was taking into account so that the velocity always lined up with your collision area when you built your maps, else it won't work, but then with the whole rails style it'd be an issue unless you had some sort of overcompensation check and had it "wrap" at the right point and switch to the alternate axis with your movement. Though that would start to get ugly most likely. Hrmmmm.Damn it my first oldschool game was going to be pong but now I'm pondering this issue =-P
#10
The original game display was 240x320 or smaller. With current resolutions, it would probably look pretty jumpy without some form of keyframing technique.
I'll take a shot at an example playfield tonight and tomorrow to see if it's easier to show via code than English :-)
03/14/2005 (4:52 pm)
Gary: The sprite would "hop" from tile to tile using absolute positioning instead of specifying a velocity. That way it's always aligned with the movement grid.The original game display was 240x320 or smaller. With current resolutions, it would probably look pretty jumpy without some form of keyframing technique.
I'll take a shot at an example playfield tonight and tomorrow to see if it's easier to show via code than English :-)
#11
Terry: An example would be great if you manage to find some spare time.
03/15/2005 (3:39 am)
If I understand you correctly, you're suggesting the pacman sits at an exact position on a tile, then when the player presses left, the pacman jumps from tile to tile using .setPosition. Upon reaching a new tile the pacman stops for a specified amount of time ( to prevent covering 10 tiles in 10frames :P) and continues until either the player trys to change direction, or we collide with a wall.Terry: An example would be great if you manage to find some spare time.
#12
Keys are W,S,A,D and need to be held until your moving in the requested direction, then they can be released and you'll keep going.
This method uses a tile map layer for the walls with collisions active. I catch the collisions and check if its player against wall. If so, I check the direction of the players movement and recenter in that axis, eg if you hit a wall moving left, your X value is set back to the center of the tile.
For changing direction whilst moving, for example to move into a gap in a wall, I catch the press of the up key and store this as nextDir = moveUp (I'm going to change this to nextDir = "0 -1" later which will allow me to simplify the code). Then in the sceneUpdate I call %player.doMovement, in the move function I check whether a direction change has been requested. If it has we mount the player on the tile they're currently in, which auto moves them to the center of the tile in a failry smooth way (this assumes the tile in the new direction is not a wall)
Later on do movement will be called again, at which point we check if the player is within a bounding box of the center of the tile, if so we snap to the center (amount is small enough so that the snap isn't really visible). Once snapped, we then setup the move in the new direction and the whole thing happens all over again :P
Still not fully happy with this method, there is a slight quirk if you keep continually changing direction on the same axis but, its an improvement on my last attempt which hogged resources. Plus this method should allow me to implement inertia if I really wanted to :P
My main reason for getting a clean method working for smooth movement isn't just for pacman, it would also be very useful for one of my future t2 tile based games. So I'm pretty keen on getting a good method going. That said, once I have something adaquat, I can always revisit this when the game is complete :P
Terry: If you can make an example that improves on my current test version I would love to see your method. There are so many different ways each with their own pitfalls, that I'm sure I've still not found the ideal solution. If you want to see the code for my current version let me know.
03/15/2005 (4:34 am)
I've had a bit more of a play around with different methods today. So far the best I've come up with is the following: pacman-move-test.rarKeys are W,S,A,D and need to be held until your moving in the requested direction, then they can be released and you'll keep going.
This method uses a tile map layer for the walls with collisions active. I catch the collisions and check if its player against wall. If so, I check the direction of the players movement and recenter in that axis, eg if you hit a wall moving left, your X value is set back to the center of the tile.
For changing direction whilst moving, for example to move into a gap in a wall, I catch the press of the up key and store this as nextDir = moveUp (I'm going to change this to nextDir = "0 -1" later which will allow me to simplify the code). Then in the sceneUpdate I call %player.doMovement, in the move function I check whether a direction change has been requested. If it has we mount the player on the tile they're currently in, which auto moves them to the center of the tile in a failry smooth way (this assumes the tile in the new direction is not a wall)
Later on do movement will be called again, at which point we check if the player is within a bounding box of the center of the tile, if so we snap to the center (amount is small enough so that the snap isn't really visible). Once snapped, we then setup the move in the new direction and the whole thing happens all over again :P
Still not fully happy with this method, there is a slight quirk if you keep continually changing direction on the same axis but, its an improvement on my last attempt which hogged resources. Plus this method should allow me to implement inertia if I really wanted to :P
My main reason for getting a clean method working for smooth movement isn't just for pacman, it would also be very useful for one of my future t2 tile based games. So I'm pretty keen on getting a good method going. That said, once I have something adaquat, I can always revisit this when the game is complete :P
Terry: If you can make an example that improves on my current test version I would love to see your method. There are so many different ways each with their own pitfalls, that I'm sure I've still not found the ideal solution. If you want to see the code for my current version let me know.
#13
Start Moving:
Use setLinearVelocity() to start moving packman in the direction the player requested (maze collisions allowing)
schedule() a function (i.e. reachedTile() ) so we know when the pacman has reached the next tile.
Reached Tile
Assert the position using setPosition(). Read what direction the player is currently requesting, and move in that direction.
You will need to match the velocity with the time to move one tile i.e.
- Time for pacman from one tile to next: 500ms (0.5 seconds)
- World units per tile: 32
- Velocity = 32 / 0.5 = 64 (i.e. needs to travel 64 world units over half a second)
So for moving right : setLinearVelocity("64 0");
You can also use this system for non-tile based movement i.e. setLinearVelocityPolar()
03/15/2005 (4:54 am)
You could use the following (I havent got time to type all the code - sorry Im at work!)Start Moving:
Use setLinearVelocity() to start moving packman in the direction the player requested (maze collisions allowing)
schedule() a function (i.e. reachedTile() ) so we know when the pacman has reached the next tile.
Reached Tile
Assert the position using setPosition(). Read what direction the player is currently requesting, and move in that direction.
You will need to match the velocity with the time to move one tile i.e.
- Time for pacman from one tile to next: 500ms (0.5 seconds)
- World units per tile: 32
- Velocity = 32 / 0.5 = 64 (i.e. needs to travel 64 world units over half a second)
So for moving right : setLinearVelocity("64 0");
You can also use this system for non-tile based movement i.e. setLinearVelocityPolar()
#14
- Melv.
03/15/2005 (5:38 am)
To do add to this discussion, eventually we'll be adding the ability to move to a particular position which will make this process much easier.- Melv.
#15
It's a known bug, and Melv already fixed it, so as soon as we get the new code, I'll publish what I have.
I thought of a way around using custom tile data by having a unique tile for every possible movement, but that's a lot of work, and a lot less elegant.
On a related note, does anyone have a utility for converting animated GIFs into a format suitable to be loaded as a T2D animated sprite?
03/15/2005 (1:56 pm)
I built a demo tile map to show one way of approaching it, but the custom tile data isn't being saved with the map, which makes it rather difficult to actually run :-)It's a known bug, and Melv already fixed it, so as soon as we get the new code, I'll publish what I have.
I thought of a way around using custom tile data by having a unique tile for every possible movement, but that's a lot of work, and a lot less elegant.
On a related note, does anyone have a utility for converting animated GIFs into a format suitable to be loaded as a T2D animated sprite?
#16
I like the GIF Construction Set Professional from Alchemy Mindworks. Allows creation or disassembly of animated GIFs. Once you extract all the frames from your animated GIF, it should be simple enough to make a sprite out of them.
Robert V Frazier
03/15/2005 (6:03 pm)
@Terry:I like the GIF Construction Set Professional from Alchemy Mindworks. Allows creation or disassembly of animated GIFs. Once you extract all the frames from your animated GIF, it should be simple enough to make a sprite out of them.
Robert V Frazier
#17
I am learing T2D too, and start writing Pacman too :)
I found your topic and very interesting in your results.
Tried to download http://www.mups.co.uk/downloads/pacman-move-test.rar
but link down.
Can you put it for downloading again?
Thank you.
04/11/2006 (6:23 am)
@GaryI am learing T2D too, and start writing Pacman too :)
I found your topic and very interesting in your results.
Tried to download http://www.mups.co.uk/downloads/pacman-move-test.rar
but link down.
Can you put it for downloading again?
Thank you.
#18
www.figmentgames.com/downloads/pacfish-v1.0.rar
If you're interested in looking through the scripts let me know your email address (either post here or email me via the email in my profile) and I'll send you the scripts.
Keep in mind though, this was written for the old version of T2D, not only will it probably not work without changes with the new version, but you may find there are much better ways to do the movement now. I'll include an exe anyway so you can at least play around with it :)
As Melv posted there were plans to allow "moveto" which would really help avoid the hackish movement code I used, not sure if this is in yet or not as I've not played around with the newer version of TGB yet, but its worth looking into.
04/11/2006 (7:53 am)
Alex: I've had a bit of a re-shuffle of my website you can download the last test version I did fromwww.figmentgames.com/downloads/pacfish-v1.0.rar
If you're interested in looking through the scripts let me know your email address (either post here or email me via the email in my profile) and I'll send you the scripts.
Keep in mind though, this was written for the old version of T2D, not only will it probably not work without changes with the new version, but you may find there are much better ways to do the movement now. I'll include an exe anyway so you can at least play around with it :)
As Melv posted there were plans to allow "moveto" which would really help avoid the hackish movement code I used, not sure if this is in yet or not as I've not played around with the newer version of TGB yet, but its worth looking into.
#19
Yep, very interesting to look at your script (I updated e-mail in my profile).
I am absolutely agree with you about that will be good start movement for me.
Also I am interesting how do you build the levels?
As I understand by tile editor, about wall all clear for me, but about dots - not. Are dots static objects setup in the level editor or not....
Oh, I have many another questions :)
Your code will wery helpful for me.
Thank, you!
04/11/2006 (10:25 pm)
Thank you very much for fast answer!Yep, very interesting to look at your script (I updated e-mail in my profile).
I am absolutely agree with you about that will be good start movement for me.
Also I am interesting how do you build the levels?
As I understand by tile editor, about wall all clear for me, but about dots - not. Are dots static objects setup in the level editor or not....
Oh, I have many another questions :)
Your code will wery helpful for me.
Thank, you!
#20
04/12/2006 (5:20 am)
Email sent (well sending :P)
Torque Owner Peter Dwyer
Pacman movement does not need to be tile by tile. What pacman does is have a linear velocity in the direction the user taps the stick. This allows for quick cornering and ghost avoidance.
The Pacman only stops when he is directly facing a wall and can therefore go no further.