只是作为这个问题的序言,请注意我不是在问“修复我的代码”,而是我将采用什么技术来修复这个问题。如果我的拼写不是很好,我也深表歉意。
好吧,我有一个 2D 平台游戏,它比较玩家的位置和所有的瓷砖(在一个循环中),相应地解决碰撞。这几乎就是主游戏循环的结构:
- 检查所有碰撞(如果碰撞低于 播放器发生)
- 获得输入并相应地改变玩家速度
- 将重力添加到 Y 速度
- 对玩家位置施加速度和摩擦力
- 绘制游戏
- 重复
但是尽管这个系统可以工作,但碰撞系统有两个小但明显的问题(我提供了图像以使其更容易)。有两个问题,第一个没那么糟糕,但第二个渲染游戏几乎无法玩!
问题 1. 在游戏中左右移动地板时,有时玩家会失去其获得的所有速度,然后必须重新积累该速度。我认为这是因为我的碰撞检测功能有时无法正常返回。这是一张图片:
我希望这很清楚,只有在穿过大片平坦的土地时,问题才会真正变得明显。
问题 2(这个更糟)问题是玩家基本上可以跳上墙,因为如果你说例如按住左箭头并按住跳跃,玩家就会跳上墙。我假设这是因为如果碰撞来自侧面,我的碰撞检测功能将返回 true(尽管它不应该)。这是另一张图(文字很小,抱歉):
所以这是我的碰撞检测函数,它应该接受两个“对象”,然后从发生碰撞的第一个对象返回方向,我认为问题是在确定方向时引起的,因为这会导致问题,如上图:
//Find the collision vectors
float vectorX = (a.Position.x + (a.Scale.x / 2)) - (b.Position.x + (b.Scale.x / 2));
float vectorY = (a.Position.y + (a.Scale.y / 2)) - (b.Position.y + (b.Scale.y / 2));
//Find the distance between the two objects
float deltaWidth = (a.Scale.x / 2) + (b.Scale.x / 2);
float deltaHeight = (a.Scale.y / 2) + (b.Scale.y / 2);
//Stores the direction of collision
Direction collisionDir = Direction::None;
//Check if the two objects are intersecting on the x and y axis
if (fabs(vectorX) < deltaWidth && fabs(vectorY) < deltaHeight)
{
//The direction of collision
float directionX = deltaWidth - fabs(vectorX);
float directionY = deltaHeight - fabs(vectorY);
//Check for vertical collision
if (directionX >= directionY)
{
//Check for collisions from the top
if (vectorY > 0)
{
a.Velocity.y = 0;
a.Position.y += directionY;
collisionDir = Direction::Up;
}
//Collisions form the botttom
else
{
a.Velocity.y = 0;
a.Position.y -= directionY;
collisionDir = Direction::Down;
}
}
else if (directionX < directionY / 2)
{
//Check for collisions from the left
if (vectorX > 0 )
{
a.Velocity.x = 0;
a.Position.x += directionX;
collisionDir = Direction::Left;
}
//Collisions form the right side
else
{
a.Velocity.x = 0;
a.Position.x -= directionX;
collisionDir = Direction::Right;
}
}
}
//Return the direction.
return collisionDir;
这将返回一个方向,我的其他代码也会检查该方向是否== Bottom,然后它将允许跳跃。
感谢您的帮助。我正在为 Ludum Dare 练习,因为我计划(可能)制作一个平台游戏,如果我不能弄清楚碰撞检测,我不知道我的游戏会有多好。
最佳答案
我建议的第一件事是让自己成为一个 Vector2D 类,它包含您的 x 和 y 坐标以及一些重载一些运算符以允许两个 Vector2D 的加法和减法以及整数、 float 和 double 的乘法和除法。相信我,这会让您的生活更轻松,因为它们可以容纳您所有的力和碰撞点。
接下来,当我使用您当前使用的碰撞样式时,我总是发现它是:
A)更难调试。
B)其他人更难遵循你的代码。
因此我建议创建一个 Rectangle2D 类来处理与其他 Rectangle 和其他所需功能的碰撞。
作为建议,将左上角和右下角作为矩形中心的 vector ,这使得缩放和碰撞检测更加容易,这也意味着您可以导出其他角而无需直接存储它们。
下面是一个代码示例,可能会对我要解释的内容有所帮助:
bool Intersects(Rectangle2D other)
{
//Checks the right, left, bottom then top of the rectangle
//against the other.
if(other.topLeftCorner.x >= bottomRightCorner.x //Checks the right
|| other.bottomRightCorner.x <= topLeftCorner.x //Checks the left
|| other.topLeftCorner.y >= bottomRightCorner.y //Checks the bottom
|| other.bottomRightCorner.y <= topLeftCorner.y) //Checks the top
return false;
else
return true;
}
您可以轻松地操纵此代码来为您指定碰撞的方向。希望这会有所帮助。
关于c++ - 2D C++ 碰撞检测几近完美,但还不够完美?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36589856/