精灵与瓦片地图的碰撞
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
不是 1
或 N_tilevalue
是 0
)那么函数 returns 在那个点在所有其他情况下。它永远无法继续进行其他碰撞检查。
所以,我正在尝试构建我自己的游戏引擎,我的第一个项目是创建一个 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
不是 1
或 N_tilevalue
是 0
)那么函数 returns 在那个点在所有其他情况下。它永远无法继续进行其他碰撞检查。