Sprite collision with tile map

时间:2015-08-07 02:25:22

标签: c++ visual-studio-2013 directx-9

So, I'm trying to build my own game engine and my first project is creating a pacman clone. I've worked out how to create the tilemap and move pacman around on it. But I've having issues creating a collision detector with the tilemap. Particularly the issue is that the collision detects fine for any tiles north of the current location, however it thinks the tile below the current location is actually 1 tile larger than normal. And 0 collision exists for tiles east and west of the current location. I'm confused because the collision works for the north tile... but I'm using the same logic for the other directions and it's not working.

The logic I am using is that 'okay' tiles to move into are value 0. Any other tile is not able for movement.

Here is the code I'm using for the actual wall collision:

//checks for a sprite colliding with a wall tile
//direction refers to 1=North, 2=South, 3=West, 4=East
bool Wall_Collision(SPRITE sprite, int direction)
{
    //grab center of sprite
    Posx = sprite.x + Sprite_Radius;
    Posy = sprite.y + Sprite_Radius;

    //create rectangle for the sprite
    RECT spriteRect;
    spriteRect.left = (long)sprite.x;
    spriteRect.top = (long)sprite.y;
    spriteRect.right = (long)sprite.x + sprite.width * sprite.scaling;
    spriteRect.bottom = (long)sprite.y + sprite.height * sprite.scaling;

    //recover North tile info
    int N_posx, N_posy;
    int N_tilex, N_tiley;
    int N_tilevalue;

    N_posx = Posx / TILEWIDTH;
    N_posy = (Posy - TILEHEIGHT) / TILEHEIGHT;

    N_tilex = N_posx * TILEWIDTH;
    N_tiley = N_posy * TILEHEIGHT;
    N_tilevalue = MAPDATA[(N_posy * MAPWIDTH + N_posx)];

    //create rectangle for tile North of sprite center
    RECT northRect;
    northRect.left = N_tilex;
    northRect.top = N_tiley;
    northRect.right = N_tilex + TILEWIDTH;
    northRect.bottom = N_tiley + TILEHEIGHT;

    //recover South tile info
    int S_posx, S_posy;
    int S_tilex, S_tiley;
    int S_tilevalue;

    S_posx = Posx / TILEWIDTH;
    S_posy = (Posy + TILEHEIGHT) / TILEHEIGHT;

    S_tilex = S_posx * TILEWIDTH;
    S_tiley = S_posy * TILEHEIGHT;
    S_tilevalue = MAPDATA[(S_posy * MAPWIDTH + S_posx)];

    //create rectangle for tile South of sprite center
    RECT southRect;
    southRect.left = S_tilex;
    southRect.top = S_tiley;
    southRect.right = S_tilex + TILEWIDTH;
    southRect.bottom = S_tiley + TILEHEIGHT;

    //recover West tile info
    int W_posx, W_posy;
    int W_tilex, W_tiley;
    int W_tilevalue;

    W_posx = (Posx - TILEWIDTH) / TILEWIDTH;
    W_posy = Posy / TILEHEIGHT;

    W_tilex = W_posx * TILEWIDTH;
    W_tiley = W_posy * TILEHEIGHT;
    W_tilevalue = MAPDATA[(W_posy * MAPWIDTH + W_posx)];

    //create rectangle for tile West of sprite center
    RECT westRect;
    westRect.left = W_tilex;
    westRect.top = W_tiley;
    westRect.right = W_tilex + TILEWIDTH;
    westRect.bottom = W_tiley + TILEHEIGHT;

    //recover East tile info
    int E_posx, E_posy;
    int E_tilex, E_tiley;
    int E_tilevalue;

    E_posx = (Posx + TILEWIDTH) / TILEWIDTH;
    E_posy = Posy / TILEHEIGHT;

    E_tilex = E_posx * TILEWIDTH;
    E_tiley = E_posy * TILEHEIGHT;
    E_tilevalue = MAPDATA[(E_posy * MAPWIDTH + E_posx)];

    //create rectangle for tile East of sprite center
    RECT eastRect;
    eastRect.left = E_tilex;
    eastRect.top = E_tiley;
    eastRect.right = E_tilex + TILEWIDTH;
    eastRect.bottom = E_tiley + TILEHEIGHT;

    RECT dest; //ignored

    //check North collision
    if (direction == 1 && N_tilevalue != 0)
    {
        return IntersectRect(&dest, &spriteRect, &northRect);
    }
    else return false;

    //check South collision
    if (direction == 2 && S_tilevalue != 0)
    {
        return IntersectRect(&dest, &spriteRect, &southRect);
    }
    else return false;

    //check West collision
    if (direction == 3 && W_tilevalue != 0)
    {
        return IntersectRect(&dest, &spriteRect, &westRect);
    }
    else return false;

    //check East collision
    if (direction == 4 && E_tilevalue != 0)
    {
        return IntersectRect(&dest, &spriteRect, &eastRect);
    }
    else return false;
}

And then the context I'm using the function to move the player sprite:

void MovePacman()
{
    if (Wall_Collision(pacman, 1))
    {
        pacman.y -= pacman.vely;
        pacman.vely = 0.0f;
    }
    else
    {
        if (Key_Down(DIK_UP))
        {
            pacman.vely = -0.2f;
            pacman.velx = 0.0f;
        }
    }

    if (Wall_Collision(pacman, 2))
    {
        pacman.y -= pacman.vely;
        pacman.vely = 0.0f;
    }
    else
    {
        if (Key_Down(DIK_DOWN))
        {
            pacman.vely = 0.2f;
            pacman.velx = 0.0f;
        }
    }

    if (Wall_Collision(pacman, 3))
    {
        pacman.x -= pacman.velx;
        pacman.velx = 0.0f;
    }
    else
    {
        if (Key_Down(DIK_LEFT))
        {
            pacman.velx = -0.2f;
            pacman.vely = 0.0f;
        }
    }

    if (Wall_Collision(pacman, 4))
    {
        pacman.x -= pacman.velx;
        pacman.velx = 0.0f;
    }
    else
    {
        if (Key_Down(DIK_RIGHT))
        {
            pacman.velx = 0.2f;
            pacman.vely = 0.0f;
        }
        else;
    }

    if (pacman.vely < 0)
        Sprite_Animate(pacman.frame, pacman.startframe, 18, 4, pacman.starttime, 250);
    else if (pacman.vely > 0)
        Sprite_Animate(pacman.frame, pacman.startframe, 16, 2, pacman.starttime, 250);
    else if (pacman.velx < 0)
        Sprite_Animate(pacman.frame, pacman.startframe, 17, 3, pacman.starttime, 250);
    else if (pacman.velx > 0)
        Sprite_Animate(pacman.frame, pacman.startframe, 15, 1, pacman.starttime, 250);

    pacman.y += pacman.vely;
    pacman.x += pacman.velx;
}

trust that I've defined everything that is not pasted and linked headers correctly. Any ideas where I'm going wrong?

1 个答案:

答案 0 :(得分:1)

您只在一种情况下检查碰撞:

//check North collision
if (direction == 1 && N_tilevalue != 0)
{
    return IntersectRect(&dest, &spriteRect, &northRect);
}
else return false;  // <--- this

//check South collision
if (direction == 2 && S_tilevalue != 0)
{
    return IntersectRect(&dest, &spriteRect, &southRect);
}
else return false;  // <--- and this, etc...

请参阅上面突出显示的行。如果它没有测试北方碰撞(即如果direction不是1N_tilevalue0)那么该函数会在此时返回在所有其他情况下。它永远不会继续进行其他碰撞检查。