我正在尝试使用SFML 2.1在c ++中制作的2D超级马里奥兄弟克隆包装碰撞。我尝试了许多不同的解决方案和想法,但我无法正常工作 我有一个目前正在检查碰撞的玩家自己的Update()(如下所示)
目前:
我的碰撞检测到碰撞略微偏移。如果你能找到任何明显的错误我会很高兴知道
2.我不确定这是否是一个足够好的解决方案,因为我需要检测4个方向的碰撞(跳跃,撞到我的头上的块。坠落到块上,左/右碰撞)
3.当我发现碰撞时,我不知道如何在正确的方向上纠正玩家。
我已经清理了所有不必要的代码并删除了以下不起作用的代码。
void Player::Update(Camera& camera, Level& level, sf::RenderWindow& window)
{
input.Update(*this); // Read input logic
physics.update(*this, level, camera, window); // Update physics (movement, gravity)
drawing.update(*this); // Update animation ( does NOT draw player )
if(Collision(level, camera, getPosition())) // Check for collision
{
CollisionResponse(); // If we had collision, do something about it
}
}
Collision()
函数有三个参数:
- 级别:是地图
- 摄像头:在屏幕上返回从地图显示的图块
- getPosition():只是玩家在窗口中的位置
该功能如下所示:
bool Player::Collision(Level& level, const Camera& camera, const sf::Vector2f& position)
{
// Rectangle surrounding player
sf::FloatRect playerRectangle = sprite.getGlobalBounds();
int tileSize = 32;
Tile* tile;
// smallBounds is the area on the screen where we check collision.
// We dont check the whole screen, only tiles that CAN collide with player.
sf::IntRect smallBounds = sf::IntRect(
(position.x / tileSize) + camera.GetTileBounds(tileSize).left,
position.y / tileSize,
((position.x + tileSize) / tileSize) + camera.GetTileBounds(tileSize).left,
(position.y + tileSize) / tileSize);
// Loop through all tiles
for (int y = smallBounds.top; y < smallBounds.height; y++)
{
for (int x = smallBounds.left; x < smallBounds.width; x++)
{
// Get the tile we are drawing
tile = level.GetTile(x, y);
if(tile && !tile->GetWalkable())
{
sf::FloatRect tileRectangle(tile->GetSprite().getPosition().x,
tile->GetSprite().getPosition().y,
tileSize,
tileSize);
tileRect = tileRectangle;
if(Intersect(playerRectangle, tileRectangle))
{
// Woah, collision detected!
return true;
}
}
}
}
return false;
}
和CollisionResponse函数:
void Player::CollisionResponse(void)
{
}
如果我错过任何有用的信息,请在下面发表评论。
地图由坐标保存的不同瓷砖组成,而不是它们实际定位的位置,但它们在阵列中的位置,因此样本地图如下所示:
0,0 0,1 0,2
1,0 1,1 1,2
2,0 2,1 2,2
然后,碰撞功能检查与玩家周围的平铺瓦片相关的碰撞。
我尝试了什么:
许多不同的碰撞方法可以同时解决x和y碰撞问题
碰撞响应将玩家移回最后位置。
碰撞响应将玩家移回到交叉矩形的大小(这在y轴上工作,但在x轴上不起作用)。
当我的头脑感觉不像融化的奶酪时,我会写得更多。
答案 0 :(得分:2)
将玩家移回最后一个已知的好位置将导致您遇到的行为;玩家将与他碰撞时保持一定距离。举一个例子:如果你的角色以300像素/秒的速度移动并且距离墙壁5个像素,则下一次碰撞发生在1/60秒。如果您的帧速率为60FPS,则在下一帧中将检测到碰撞,并且角色将移回到碰撞发生前他所在墙壁的5个像素。当然不受欢迎。
只要您正确计算数量,您所使用的方法就可以工作(将播放器移回相交矩形的大小)。 Separating Axis theorem对此有好处(在那篇文章中,具体见第7节“寻找MTV”)。
您可以尝试的另一种方法,不涉及计算:在碰撞时,将玩家向后移动一小段时间(甚至可能是逐像素)直到他停止与墙壁碰撞。然后,你会知道一个靠近墙壁的地方,放置他是安全的。效率较低,但更容易实施。
另一种方法是连续碰撞检测。它本质上更复杂一些。你应该能够通过搜索“连续碰撞”来找到它的一些信息,但基本的想法是:
答案 1 :(得分:1)
对于我的游戏(在带有Libgdx的java中)我也使用了AABB碰撞检测。您可以通过两种不同的方式来检测和处理碰撞:
当您使用TileBased
地图时,您不需要使用&#34;十字路口&#34;试验。
相反,你可以存储你角色的4个角点,四舍五入到他所在的Tile
(如果每个Tile
是一个单位大而字符英尺在P(0.5; 0.5),你需要检查Tile
(0; 0))
Player
的位置是他的左下角(通常),所以他的其他3个点是P2(player.position.x.+player.width;player.position.y)
,P2(player.position.x.+player.width;player.position.y+player.height)
,P3(player.position.x;player.position.y+player.height)
,总是向下舍入到{Tile
1}}的位置。
希望它有所帮助。