2

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

user1767316
  • 3,276
  • 3
  • 37
  • 46
Androme
  • 2,399
  • 4
  • 43
  • 82
  • 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 Dec 18 '15 at 17:14

2 Answers2

2

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 :)

IanMelrose
  • 108
  • 7
0

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);
blubb
  • 9,510
  • 3
  • 40
  • 82
  • The reason i multible my Title Size is because curTitle.X is the title number but not the posision of the title, each title is map.TileSize * map.TileSize so the start location of title 3,2 is (3 * map.TileSize),(2 * map.TileSize) – Androme Jan 25 '12 at 09:48
  • You'd be better off working in logical world coordinates (tile indices) rather than screen coordinates (tile sizes) for collision detection.. Can you calculate the position of pacman in terms of tile index? – MattDavey Jan 25 '12 at 09:53
  • @DoomStone: That makes sense. In this case, I don't immediately see the error, though. – blubb Jan 25 '12 at 09:54
  • @MattDavey Yes see the function GetCurrentTitle(), it will return what title the upper left corner the pacman sprite are in. That was how i started the calculation, but that went even more wrong then the current method. – Androme Jan 25 '12 at 10:51