You're over thinking this - using collisions is way too complex for the goal of a Pac-Man clone. Consider a grid approach instead, and forget collisions. If your goal is to create a clone, this is about functionality, not fads.
Why a Grid?
Give yourself the following conditions for a grid approach...
- Movement is only at 90 degree angles (up, down, right, left)
- Pellets exist only on grid points
- The player will come to a stop on a grid point if no arrow keys (or joystick or whatever) is pressed
- Wall/solid elements also exist only on a grid point
- Map is wrappable - player can exit one side and come back onto the other side
Keep It Simple!
So basically create a 2d array the size of your map, where each entry has a value of 0 for empty, 1 for a pellet, and 2 for solid (no walk). Then, when you are trying to decide if the player can move to an adjacent cell, simply check the target cell location to see if it's solid or not. If so, no movement allowed. If solid, movement allowed. If occupied by a pellet, award a point and remove the pellet.
Put your player at some starting coordinate that is not solid with no movement. Now whenever the player wants to move, check the target cell to see if it is free (i.e., not solid). If so, move player to that spot. If there's a pellet there, give them a point. And if you allow coordinates to wrap, you can easily handle maps that wrap (e.g., go off left side of map and come back on on right).
The best thing about this approach is that it's massively portable. You could use this to make it with JavaScript/CSS or even text-based.
Advantages
- Super simple implementation
- Handles map wraparound in a trivial way
- Extremely portable to any environment (even a text based game on an old DOS box)
- Simple solution lets you concentrate on the real challenge, which is modelling Ghost movement :)
- Probably how the original works
- Bragging rights over how "incredibly simple the implementation is"
Disadvantages
- Doesn't work for curved, non-linear paths
- No bragging rights over how "incredibly complex the implementation is"
Pseudo Code
Here's some pseudocode...
// --- Map constants and vars
define MAP_WIDTH 20
define MAP_HEIGHT 20
define EMPTY 0
define PELLET 1
define SOLID 2
var map[GRID_WIDTH, GRID_HEIGHT];
// --- Built map
map = build_map();
// --- Start player at [1,1], which is open
player_x = 1;
player_y = 1;
while (game_active) {
// --- Scoring check
if (map[player_x, player_y] == PELLET) {
// --- Pellet in player spot, so give point and remove pellet
score += 1;
map[player_x, player_y] = 0;
}
// --- Set target_x/y to where player will go (default to nowere)
target_x = player_x;
target_y = player_y;
// --- keypress check for movement. If target cell is free, player moves there
switch (key) {
case 'W': // up
// --- Test one map cell up, allowing for possible map wrap
target_y = player_y - 1;
if (target_y < 0) target_y += MAP_HEIGHT;
break;
case 'A': // left
target_x = player_x - 1;
if (target_x < 0) target_x += MAP_WIDTH;
break;
case 'S': // down
target_y = player_y + 1;
if (target_y >= MAP_HEIGHT) target_y -= MAP_HEIGHT;
break;
case 'D': // right
target_x = player_x + 1;
if (target_x >= MAP_WIDTH) target_x -= MAP_WIDTH;
break;
default:
// --- Do nothing
break;
}
// --- Check if target for player movement is not solid
if (map[target_x, target_y] != SOLID) {
// --- target point is NOT solid
// --- Presume this handles animating movement and setting player pos to target
move_player_to(target_x, target_y);
} else {
// --- Player target is solid, so do nothing
}
// --- Perform monster logic
move_monsters();
// --- Render map
render_map();
}