【问题标题】:C++ Collision Detection doesn't work on last check?C++ 碰撞检测在最后一次检查中不起作用?
【发布时间】:2013-03-21 17:55:07
【问题描述】:

在过去的几天里,我一直在尝试对使用 OpenGL 绘制的对象进行简单的碰撞检测。 在Pearson, Computer Graphics with OpenGL 的帮助下,我设法编写了以下函数:

void move(){
    if(check_collision(sprite,platform1) || check_collision(sprite,platform2)){ //if colliding...
        if     (downKeyPressed ){ y_Vel += speed; downKeyPressed  = false;} //going down
        else if(upKeyPressed   ){ y_Vel -= speed; upKeyPressed    = false;} //going up
        else if(rightKeyPressed){ x_Vel -= speed; rightKeyPressed = false;} //going right
        else if(leftKeyPressed ){ x_Vel += speed; leftKeyPressed  = false;} //going left
    } // always glitches on whatever is last else if above?!?!
    else{ glTranslatef(sprite.x+x_Vel, sprite.y+y_Vel, 0.0); }
}

我的精灵根据键盘输入(箭头键)移动。如果它与静止的物体碰撞,它会停止移动并保持在原来的位置。

到目前为止,它在与静止物体的顶部、左侧和底部发生碰撞时起作用。不幸的是(即使我使用相同的逻辑)右侧不起作用,并且在发生碰撞时,精灵会在其原始 x/y 坐标处重新绘制。我很困惑。

事实证明,move() 函数中的最后一个检查(最后一个 else-if)是不起作用的...我已将 left 替换为 @987654326 @ 果然left 是最后一个,也是最后一个播放的:(

关于如何改进它并阻止它出现故障的任何建议或想法?

请原谅我的天真和业余编码。我只是一个自学的开始。谢谢。

【问题讨论】:

  • 我会尝试将float speed 更改为int speed 以及x_vel 和y_vel,首先排除舍入错误问题...
  • 另外,不清楚你说的redrawn at original x/y coordinates是什么意思
  • 谢谢,我马上改一下类型。在按下任何键之前,精灵被绘制在屏幕的左下角,当它与静止物体的右侧发生碰撞时,它基本上会删除精灵并将其移动/重绘回左下角......

标签: c++ collision-detection


【解决方案1】:

你不应该使用 else if。它有可能在同一帧中撞击侧面和顶部或底部。尝试将这些更改为所有如果,因为您想检查每一个。或者至少改成这个。

if( /* check top */)
{

}
else if( /* check bot */)
{

}

if( /* check right */ )
{

}
else if( /* check left */)
{

}

此外,您应该避免声明像 Y_VEL 和 X_VEL 这样​​的全局变量,因为这会造成混淆。你这样做可能只是为了弄湿你的脚,但我会避免这样做。为每个对象创建一个类,然后将速度作为该类的成员。

【讨论】:

  • 好的,谢谢你告诉我。这很有意义。我现在已经改变了。不幸的是,它并没有解决故障
  • 你有没有想过这个问题?我很好奇。
【解决方案2】:

嗯,在我看来,您在翻译实际对象时遇到了问题。 您的移动代码状态

if(there is a collision)
{ 
    //do stuff
}
else
{
    glTranslateF( );
}

所以,每当发生碰撞时,翻译函数永远不会被调用。

我的意见是你应该把glTranslateF() 调用从else {...} 中拉出来,每次都调用它。但是,您似乎对每个矩形都使用了完全相同的“绘制”函数,而不仅仅是玩家精灵。您可能必须找到一种方法来区分常规矩形(例如平台)和播放器矩形。也许实现这一点的最简单方法是使用两个不同的drawSprite 函数:一个用于常规平台,另一个用于播放器。只能从玩家的绘图函数中调用move() 函数(可能称为drawPlayer()?)

目前我没有时间查看您的所有代码以提出更有根据和更具体的建议;不过,如果这个问题仍然悬而未决并且需要帮助,我将在今晚晚些时候有空。

【讨论】:

  • 我想我明白你在说什么。但是,我确实有两个功能可以进行绘图。一个用于 Sprite,另一个用于 2 个单独的平台。如果你以后有时间那就太好了,我很感激我能得到任何帮助。
  • @Serge 顺便说一句,他以一种根本不需要翻译的方式绘制精灵:glVertex3f(rect.x, rect.y+rect.h, 0.0); - 他自己移动顶点。
  • 问题是,如果我删除glTranslate,按下键时精灵不会移动...
  • 它终于明白了你的意思。我已经从else{...} 中取出glTranslate() 调用(每次都调用它),现在它会碰撞所有边缘,而不仅仅是顶部、左侧和底部。感谢您花时间发布您的答案。我会再做一些检查,但我认为问题就解决了。 :)
  • @Reanimation 刚刚发布并删除了两个愚蠢的 cmets。等我有更多的时间集中注意力,我会回来的,对不起!
【解决方案3】:

正如您已经发现的那样,问题与 glTranslate() 有关。由于您对精灵的位置和速度都进行了操作,因此您应该使用速度重复更新位置。那就是:

sprite.x += x_vel;
sprite.y += y_vel;

并且一直简单地执行(即通过某个计时器或每一帧,如果场景被重复重绘)。然后,碰撞相当于以某种方式更改速度矢量 (x_vel, y_vel) 以模拟碰撞效果:要么将其归零以完全停止任何运动,要么更改速度分量符号(x_vel = -x_vel) 使其绝对反弹弹性的方式,或者做其他适合的事情。

glTranslate() 现在发生的情况是,x_vel, y_vel 实际上保持与起始位置的偏移,但不保持移动速度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多