2011-09-02 155 views
2

我正在做一个简单的2D游戏(鸟瞰图)。我有射弹,它们是圆圈。围绕游戏关卡存在障碍,这些都是矩形(轴对齐)。我希望弹丸在碰撞时能够从障碍物上弹开。我不知道如何在我的游戏循环中实现这一点。猜测它会是这样的:游戏循环中的碰撞检测?

void gameLoop() { 

    Projectile p = ..; 

    p.updateLocation(p.getVelocity(), p.getDirection()); 

    Barrier intersected = p.intersects(barriers); 
    if (intersected != null) { 
     // We hit a barrier after moving on this time tick. 
     // Figure out where our reflected location off the 
     // barrier should be now. 
     Point ptNew = intersected.reflect(p.getLastPoint(), p.getVelocity(), 
      p.getDirection()); 

     // Our new location after getting bounced off the barrier. 
     ptNew.setLocation(ptNew); 
    } 
} 

所以当我们移动弹丸,我们可以检查,如果我们相交(或完全内)的障碍之一。如果是这样,做一个计算,找出我们的反射位置应该离开我们的起点和速度/方向的障碍。

感谢

----------更新------------------------

小更具体一点 - 考虑到Erik的评论,我确实需要确保弹丸正常弹跳,如果它们的速度恰好如此之快,我们就不能让它们通过障碍,它们会在单个游戏循环迭代中顺利完成。在这种情况下,我想我需要测试一个起点,速度,方向,对所有障碍(可能反复),直到不再有可能的速度交点。例如:

void gameLoop() { 
    Projectile p = ...; 

    Barrier barrier = moveProjectile(p, barriers); 
    while (barrier != null && p.stillHasVelocityThisFrame()) { 
     barrier = moveProjectile(p, barriers); 
    } 

    // at this point, the projectile is done moving/bouncing around. 
} 

void moveProjectile(Projectile projectile, 
        List<Barrier> barriers) 
{ 
    for (Barrier barrier : barriers) { 
     // tbd 
     Barrier intersected = test2dVectorAgainstRectangle(
      projectile.getPosition(), 
      projectile.get2dVector()); 
     // the above would test the projectile's vector 
     // to see if it intersects any barrier, reflect 
     // off of it if necessary, modify the projectile's 
     // position, and reduce the available distance it 
     // can still travel for this frame. 
     if (intersected) { 
      return intersected; 
     } 
    } 

    // no intersections. 
    return null; 
} 

是的,这已经变得棘手。

感谢

+0

其中的这部分,你需要帮助的?碰撞本身还是反射?或者两者兼得? – MGZero

+0

嗯,我不知道该怎么做(代码示例或链接会很棒),但是如果这是如何完成的话,更多的是寻找一般性的yes/no。 – user291701

+0

这是一个非常开放的问题 – Erik

回答

2

您希望使用矢量数学您的反射和碰撞检测。这是非常直接的检测,如果你是在一条线(世界矩形边缘)的一侧,并在该线的另一侧接下来。同样的支票也会让你碰到更多的数学碰撞点。然后你有一个点来反思,再次使用矢量。绘制与其他物体的碰撞有点诡计,但仍然可以完成。列出一个循环中的所有碰撞列表,并尝试找到沿着它们的移动路径出现的第一个 - 再次使用某些点积魔术。或者,如果您检测到多次碰撞,则可以始终备份每个对象,使其位于之前的位置,并从那里应用碰撞。你永远要做到

一件事是让物体停留另一个对象内。它可能会导致它们彼此卡住,并且行为非常不稳定 - 取决于您如何执行碰撞代码。

2

碰撞检测是很难得到的权利。这真的取决于你想要的东西是多么“完美”。

需要思考的几件事:
1)如果p移动得太快,直接通过一个更新而不经过一次更新就会发生什么?你真的需要检查p的路径是否与屏障相交。

2)如果p在穿过更新刻度的中途与屏障相交,但是在新的刻度结束之前如果与另一个屏障(或另一个p)相交,则会发生什么?您必须在单个更新记录中多次更新p的速度。

或者你可以忽略这些案件,希望事情工作了/不经常发生;)

+0

是的完美的这些是我需要警告的问题! – user291701

1

对于碰撞...... 什么你要找的是的中心之间的距离圆和矩形上的任意点。如果任何给定点之间的距离小于圆的半径,则发生碰撞。你可以使用毕达哥拉斯定理。

If (sqrt((circle.x - rect.x)² + (circle.y - rect.y)²) <= circle.radius) 
    circle.reflect(); 

至于反射... 这是很好的了解一些事情是入射角等于反射角,但负。因此,以45度的角度撞击表面的抛射体将以-45度反弹。这将要求你知道抛射体正在移动的方向(角度)以及表面的角度。如果你总结这些,你会得到你的角度。把它乘以-1,然后重新计算弹头的方向。

circle.velocity.x = cos(angleInc); circle.velocity。y = sin(angleInc);

+1

很多,只是使用矢量数学更好... –

+0

@Michael Dorgan好点,同意。我假设你只是指反射本身而不是碰撞检测? – MGZero

1

如果障碍的位置是固定的,你可以使用它的速度计算球下一个gameloop的位置,如果它的位置将超越下一次循环的障碍,你可以设置一个布尔值来设置球在下一个循环开始时紧挨着其中一个障碍物,并在检查到它们有效碰撞后相应地进行计算。

我不会赌这是做的最有效的方法,但它不应该妨碍你的游戏在所有如果它是一个2D游戏。

而且,总是试图设置限制在球上的最高速度,如果他们变得越来越快,每过gameloop,你是在自找麻烦。