2D C ++碰撞检测几乎完美,但不完全?

时间:2016-04-13 06:03:01

标签: c++ collision-detection physics game-physics sdl-2

只是为了预先提出这个问题,请注意我并没有要求修复我的代码,而是采用了哪些技术来解决这个问题。如果我的拼写不是很好,我也会道歉。

好的,所以我有一个2D平台游戏,它将玩家的位置与所有的棋子进行比较(在一个循环中),相应地解决了碰撞。这几乎是主要游戏循环的结构:

  1. 检查所有碰撞(如果碰撞发生碰撞,则启用跳跃 球员发生了)
  2. 获取输入并相应更改玩家速度
  3. 将重力添加到Y速度
  4. 对球员位置施加速度和摩擦力
  5. 绘制游戏
  6. 重复
  7. 但是,尽管这个系统工作,但碰撞系统有两个小的,但明显的问题(我提供了图像以使其更容易)。有两个问题,第一个不是那么糟糕,但第二个渲染游戏几乎无法播放!

    问题1.当在游戏中左右移动时,玩家偶尔会失去它所获得的所有速度,然后必须重新累积该速度。我想这是因为偶尔我的碰撞检测功能不能正常返回。这是一张图片:

    The prblem that is occuring

    我希望很明显,这个问题只有在穿越大片平地时才会变得明显。

    问题2(这个更糟糕)问题是玩家可以基本上跳墙,因为如果你说例如按住左箭头并按住跳跃,玩家将跳到墙上。我假设这是因为我的碰撞检测功能在碰撞来自侧面时返回true(尽管它不应该)。这是另一张图片(文字很小,对不起): Edge collision bug

    所以这是我的碰撞检测功能,它应该包含两个对象'然后从碰撞发生的第一个物体返回方向,我认为当确定方向时会引起问题,因为这会引起问题,如上所示:

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

    这将返回一个方向,我的其他代码也检查该方向==底部,然后它将允许跳跃。

    感谢您的帮助。我正在为Ludum Dare练习,因为我计划(可能)制作一个平台游戏。如果我无法弄清楚碰撞检测,我就不知道我的游戏会有多好。

    无论如何谢谢 - Coder Cameron

1 个答案:

答案 0 :(得分:3)

我建议的第一件事就是让自己成为一个Vector2D类,它保存你的x和y坐标,并且一些运算符重载一些运算符,允许两个Vector2D的加法和减法以及乘法,浮点数和双精度的乘法和除法。相信我,它会让你的生活变得更轻松,因为它们可以容纳你所有的力量和碰撞点。

接下来当我使用你正在使用的碰撞风格时,我总是发现它:

A)难以调试。

B)其他人更难以遵循您的代码。

所以我建议创建一个Rectangle2D类来处理与其他Rectangle的冲突和其他所需的功能。

建议将左上角和右下角作为矩形中心的矢量,这使得缩放和碰撞检测变得更加容易,这也意味着您可以在不直接存储它们的情况下导出其他角落。 / p>

这是一个代码示例,可能有助于我尝试解释的内容:

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

您可以轻松操作此代码,为您提供碰撞的方向。希望这会有所帮助。