游戏循环中的碰撞检测?

时间:2011-09-02 19:48:05

标签: collision-detection

我正在开发一个简单的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;
}

是的,这已经变得有点棘手了。

由于

4 个答案:

答案 0 :(得分:2)

碰撞检测很难做到。这实际上取决于你想要的东西是多么“完美”。

要考虑的几件事:
1)如果p移动得如此之快以至于在一次更新中直接穿过障碍而没有相交,会发生什么?你真的需要检查p的路径是否与屏障相交。

2)如果p在更新标记的中途与屏障相交,但是如果在更新标记结束之前与另一个屏障(或另一个p)相交,那么它的新速度会发生什么?您必须在一次更新时间内多次更新p的速度。

或者你可以忽略这些情况并希望事情能够解决/不经常发生;)

答案 1 :(得分:2)

您希望使用矢量数学进行反射和碰撞检查。很容易检测到你是否在1 tic的一条线(世界矩形的边缘)的一侧,然后在该线的另一侧。同样的检查也会让你在碰到更多数学时碰撞。然后你有一个点来做反射,再次使用向量。绘制与其他对象的碰撞有点过时,但仍然可以完成。在一个循环中列出所有碰撞,并尝试找到沿着它们的运动路径发生的第一个碰撞 - 再次重复使用一些点积魔术。或者,如果您检测到多个碰撞,您始终可以将每个对象备份到它之前的tic位置并从那里应用碰撞。

您永远不想做的一件事是允许对象留在另一个对象中。它可能导致它们相互卡住并且行为非常不稳定 - 取决于您如何处理碰撞代码。

答案 2 :(得分: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);

答案 3 :(得分:1)

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

我不打赌这是最有效的方法,但如果它是2d游戏,它根本不应该妨碍你的游戏。

另外,总是尝试设置球的最大速度限制,如果每次传球都变得越来越快,你就会遇到麻烦。