精灵与瓦片地图的碰撞

Sprite collision with tile map

所以,我正在尝试构建我自己的游戏引擎,我的第一个项目是创建一个 pacman 克隆。我已经弄清楚如何创建 tilemap 并在其上移动 pacman。但是我在使用 tilemap 创建碰撞检测器时遇到了问题。特别的问题是碰撞检测到当前位置以北的任何瓦片都很好,但它认为当前位置下方的瓦片实际上比正常大 1 个瓦片。当前位置以东和以西的方块存在 0 次碰撞。我很困惑,因为碰撞适用于北瓷砖......但我对其他方向使用相同的逻辑但它不起作用。

我使用的逻辑是 'okay' 个要移动的方块的值为 0。任何其他方块都不能移动。

这是我用于实际墙壁碰撞的代码:

//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;
}

然后是我使用函数移动玩家精灵的上下文:

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;
}

相信我已经定义了所有未正确粘贴和链接的内容 headers。我哪里出错了?

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

//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)那么函数 returns 在那个点在所有其他情况下。它永远无法继续进行其他碰撞检查。