碰撞矩形响应


10

我很难让一个可移动的矩形与多个矩形碰撞。

我正在使用SFML,它有一个方便的函数intersects,它需要2个矩形并返回交集。我有一个充满矩形的向量,我希望我的可移动矩形发生碰撞。我使用以下代码(p是可移动矩形)遍历此代码。

IsCollidingWith返回布尔值,但也使用SFML intersects来计算交叉点。

while(unsigned i = 0; i!= testRects.size(); i++){
   if(p.IsCollidingWith(testRects[i]){
        p.Collide(testRects[i]);
   }
}

和实际的Collide()代码:

void gameObj::collide( gameObj collidingObject ){

 printf("%f %f\n", this->colliderResult.width, this->colliderResult.height);

if (this->colliderResult.width < this->colliderResult.height) {
    // collided on X
    if (this->getCollider().left < collidingObject.getCollider().left ) {
        this->move( -this->colliderResult.width , 0);
    }else {
        this->move( this->colliderResult.width, 0 );
    }

}

if(this->colliderResult.width > this->colliderResult.height){
    if (this->getCollider().top < collidingObject.getCollider().top ) {
        this->move( 0, -this->colliderResult.height);
    }else {     
        this->move( 0, this->colliderResult.height );
    }

}

IsCollidingWith()代码是:

bool gameObj::isCollidingWith( gameObj testObject ){
if (this->getCollider().intersects( testObject.getCollider(), this->colliderResult )) {
    return true;
}else {
    return false;
}

Rect场景中只有1个时,这可以正常工作。但是,如果有多个Rect碰撞,则一次解决2个碰撞会引起问题。

知道如何正确处理吗?我已将视频上传到youtube以显示我的问题。最右边的控制台显示了相交的宽度和高度。您可以在控制台上看到它正在尝试一次计算2次碰撞,我认为这就是问题所在。

最后,下图似乎很好地说明了我的问题:

矩形与其他多个矩形碰撞


视频链接已断开。
传Yu

collider返回的对象是否this->getCollider()this->move()?? 更新?
传Yu

您能补充些其他信息吗?到底是什么问题?YouTube视频似乎显示出可预测的行为,并且场景中只有另一个矩形。
Wackidev

Answers:


3

您的图像说明了尝试使用凸形(尤其是矩形)来模拟平坦表面(如地板)的众多问题之一。该算法导致字符卡在组成地板的形状的内部边缘上。

一个简单的解决方法是仅检查垂直碰撞,对其进行更正,然后再次检查水平碰撞。除非您要摔倒并试图从墙壁上滑下来,否则在这种情况下,您首先要检查水平碰撞。您怎么知道什么时候先检查哪个?您可以根据速度的哪个分量较大来执行此操作(如果水平运动较大,请首先检查垂直碰撞,否则请检查水平碰撞)。

甚至更简单,更高效的方法是为您的世界生成边缘列表。也就是说,对于组成地板的盒子,设置一个标志,指示只有它们的顶部边缘实际上是可碰撞的,然后忽略与其他边缘的碰撞。您将不能为此使用SFML的碰撞例程,但是说实话,框碰撞可能是您在游戏中编写的最简单的代码。如果您的世界与网格对齐,则此技术特别有效。我将查看有关该技术的出色的Metanet教程(http://www.metanetsoftware.com/technique.html/)。

在尝试像您一样构建简单的2D平台游戏时,您将遇到许多其他问题。到目前为止,我所看到的关于此的最佳资源是以下内容,您应该阅读以下内容,然后再次阅读:

http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/



0

我认为计算2个碰撞不是问题,而只是性能问题。为了正确处理碰撞,可能必须测试两次。使用您的图表,认为如果首先针对B测试了A,那么也需要针对其他框进行测试,并且很可能与另一个碰撞。

希望对您有帮助吗?


0

这是不是一个真正的最佳方法,你应该尝试,以确定有最早时间或沿着移动的第一个点对象路径,其中发生碰撞和移动(在计算时间或位置)的对象是位置,试图根据移动后的穿透位置进行正确定位是很成问题的,但是您只需稍作更改即可使用当前的流程。一直检查碰撞,直到没有碰撞为止。

bool collided = true;
while(collided) {
   collided = false
   while(unsigned i = 0; i!= testRects.size(); i++){
      if(p.IsCollidingWith(testRects[i]){
         collided = true
         p.Collide(testRects[i]);
      }
   }
}

请注意,在某些情况下这会导致无限循环(例如,将盒子从碰撞中移出会导致另一个集合,而从碰撞中移出盒子会将其移回与以前相同的碰撞位置的情况)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.