0

如何计算 C++ 和 SDL 中两个矩形之间的碰撞,以及如何让玩家无法通过这个矩形(即确保一个矩形不能通过另一个矩形)?

我知道停止玩家会是playeryvel = 0,使玩家的 Y 速度为 0,因此他们无法通过它。我的问题是,当我想停止通过另一个矩形移动时,这将停止所有垂直移动。

我当前的代码使用了一个名为check_collision(SDL_Rect, SDL_Rect). 这是我的用法代码和实际功能。

// This loops through a vector, containing rects.
for (int i=0; i<MAP::wall.size(); i++)
{
    std::cout << i << std::endl;
    cMap.FillCustomRect(MAP::wall.at(i), 0xFFFFFF);
    if (check_collision(cMap.wall.at(i), cDisplay.getPlayer(playerx, playery)))
    {
        exit(0); // It exits just as an example to show if there actually is a collision
    }
}


bool check_collision( SDL_Rect A, SDL_Rect B )
{
    //The sides of the rectangles
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;

    //Calculate the sides of rect A
    leftA = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;

    //Calculate the sides of rect B
    leftB = B.x;
    rightB = B.x + B.w;
    topB = B.y;
    bottomB = B.y + B.h;

     //If any of the sides from A are outside of B
    if( bottomA <= topB )
    {
        return false;
    }

    if( topA >= bottomB )
    {
        return false;
    }

    if( rightA <= leftB )
    {
        return false;
    }

    if( leftA >= rightB )
    {
        return false;
    }

    //If none of the sides from A are outside B
    return true;
}
4

4 回答 4

3

只需将玩家推离碰撞点,每一帧。您不需要布尔测试(碰撞与否),如果发生碰撞,您需要调整玩家位置。

  1. 更新玩家位置(位置+=速度*时间);
  2. 如果发生碰撞,请将玩家推离碰撞点,以免发生碰撞。

这可以很好地工作,因为您将能够沿着墙壁“滑动”等。为此,您需要找到接触点、交叉深度和交叉方向(即您应该将玩家推向哪个方向走开)。

当然,你需要计算你应该移动玩家多远,但在 2D 中这非常容易做到。

您需要计算两个矩形重叠的程度。然后你将玩家矩形推向重叠最多的方向(x 或 y)(仅在 x 或 y 方向,除非它们相等)。

于 2012-02-28T19:43:16.783 回答
2

在移动功能中添加检查碰撞。将新位置(好像它已移动)传递给检查碰撞功能。如果发生碰撞,则在move func中返回false,如果没有move,则返回true。

于 2012-02-28T21:52:54.583 回答
2

我看到你使用了 Lazyfoo 代码。我也是。我和你有同样的问题,但我解决了。我是这样做的。

hero.move(true);   // hero is moved in some direction 
if (check_collision(hero.rect(),box.rect()))  // check for collision after movement 
{
    hero.move(false); // if collision happend , move hero back 
}

SDL_flip(screen);

它看起来像英雄已经停在块上,但实际上它会向前移动,如果发生碰撞,则向后移动。在此之后,他将被展示。true 和 false 参数用于告诉函数英雄必须向前移动(x += 速度)还是向后移动(x -= 速度)。如果您需要我的碰撞代码中的一些代码,请询问。

于 2013-06-20T21:00:56.297 回答
1

听起来您只是在事后才发现碰撞。很可能您正在将玩家移动到矩形中,因此后续的碰撞检查总是返回 true。有几种方法可以解决这个问题,但我认为最简单的方法是在碰撞发生之前而不是之后捕捉并防止它发生。

假设玩家正在坠落,并且您每帧更新玩家的位置。在你移动玩家的位置改变之前,你要检查新位置是否会与一个矩形相交。如果新位置将与矩形相交,您需要更改玩家移动的距离(我们将此距离称为step),使其接触矩形的边缘,但不与其相交。

于 2012-02-28T19:25:41.193 回答