2
votes

I am trying to create a pacman game to learn XNA, but I am having some problems to get the collision detection working. The game is tile based, where 1 is a wall and 0 is walkable. It then takes the tile you are standing on plus the 4 around it, and if it collides with one of them and the tile value is not 0 will it reset the position to what it was before the move. For some reason however it just doesn't work, it gets randomly stuck and sometimes I can even move though walls. enter image description here

Here is my collision detection:

    var oldPos = Position;
    // Updates the Position
    base.Update(theGameTime, mSpeed, mDirection);

    // Test Collidetion
    Rectangle objRect = new Rectangle((int)Position.X, (int)Position.Y, 32, 32);
    bool isCollided = false;
    Vector2 curTitle = GetCurrentTitle();

    // Test UP, DOWN, LEFT, RIGHT
    int tile;
    Rectangle testRect;

    if ((int)curTitle.Y < 0 || (int)curTitle.X < 0 || (int)curTitle.Y >= map.MapSizeWidth - 1 || (int)curTitle.X >= map.MapSizeHeight - 1)
        isCollided = true;

    if (!isCollided)
    {
        tile = map.Tiles[(int)curTitle.Y, (int)curTitle.X];
        testRect = new Rectangle(((int)curTitle.X) * map.TileSize, ((int)curTitle.Y) * map.TileSize, map.TileSize, map.TileSize);
        if (tile != 0 && rectangle_collision(testRect, objRect))
            isCollided = true;

        if (curTitle.Y != 0)
        {
            tile = map.Tiles[(int)curTitle.Y - 1, (int)curTitle.X];
            testRect = new Rectangle(((int)curTitle.X) * map.TileSize, ((int)curTitle.Y - 1) * map.TileSize, map.TileSize, map.TileSize);
            if (tile != 0 && rectangle_collision(testRect, objRect))
                isCollided = true;
        }

        tile = map.Tiles[(int)curTitle.Y + 1, (int)curTitle.X];
        testRect = new Rectangle(((int)curTitle.X) * map.TileSize, ((int)curTitle.Y - 1) * map.TileSize, map.TileSize, map.TileSize);
        if (tile != 0 && rectangle_collision(testRect, objRect))
            isCollided = true;

        if (curTitle.X != 0)
        {
            tile = map.Tiles[(int)curTitle.Y, (int)curTitle.X - 1];
            testRect = new Rectangle(((int)curTitle.X - 1) * map.TileSize, ((int)curTitle.Y) * map.TileSize, map.TileSize, map.TileSize);
            if (tile != 0 && rectangle_collision(testRect, objRect))
                isCollided = true;
        }

        tile = map.Tiles[(int)curTitle.Y, (int)curTitle.X + 1];
        testRect = new Rectangle(((int)curTitle.X + 1) * map.TileSize, ((int)curTitle.Y) * map.TileSize, map.TileSize, map.TileSize);
        if (tile != 0 && rectangle_collision(testRect, objRect))
            isCollided = true;
    }
    if (isCollided)
        Position = oldPos;

Can any one see why my collision detection is not working?

EDIT: I have uploaded the whole project to http://sogaard.us/Pacman.zip

2
I wouldn't allow it to move and move it back - I would stop it moving in the first place - way more efficient and may render better.niico

2 Answers

2
votes

I'm not sure if this is causing the full problem. But on your third tile check (where you check the tile below) you are checking the tile above again.

This part here:

tile = map.Tiles[(int)curTitle.Y + 1, (int)curTitle.X];

On the next line you still have this inside the params for the testRect:

((int)curTitle.Y - 1) * map.TileSize

Should be:

((int)curTitle.Y + 1) * map.TileSize

Full corrected snippet:

tile = map.Tiles[(int)curTitle.Y + 1, (int)curTitle.X];
    testRect = new Rectangle(((int)curTitle.X) * map.TileSize, ((int)curTitle.Y + 1) * map.TileSize, map.TileSize, map.TileSize);
    if (tile != 0 && rectangle_collision(testRect, objRect))
        isCollided = true;

Hope this helped :)

0
votes

This line looks odd to me:

testRect = new Rectangle(
    ((int)curTitle.X) * map.TileSize, 
    ((int)curTitle.Y) * map.TileSize, 
    map.TileSize, 
    map.TileSize);

Why do you multiply the X and Y coordinate with the TileSize?

I don't know what the parameters for Rectangle are supposed to mean, but I assume the first two are positions and the last two width and height. I guess you meant to write

testRect = new Rectangle(
    ((int)curTitle.X), 
    ((int)curTitle.Y), 
    map.TileSize, 
    map.TileSize);