【问题标题】:Collision detection in Java game?Java游戏中的碰撞检测?
【发布时间】:2010-03-15 04:56:16
【问题描述】:

我正在开发一款游戏,其中存在运动图像的碰撞检测问题。游戏中有一艘宇宙飞船和许多小行星(障碍物)。我想检测它们之间的碰撞。我该怎么做?

【问题讨论】:

    标签: java collision-detection


    【解决方案1】:

    对于矩形以外的任何东西,碰撞检测通常都很棘手。

    我过去这样做的方式是为每个对象提供图像和蒙版。例如,来自Lost in Space 的像 Jupiter 2 宇宙飞船这样的物体将具有以下图像和掩码:

         X            00000100000
      XXXXXXX         00111111100
     X       X        01111111110
    X         X       11111111111
     X       X        01111111110
      XXXXXXX         00111111100
        XXX           00001110000
    

    image 是在屏幕上显示的,而 mask 是用于碰撞检测的。您会注意到掩码中的 1 基本上是图像的轮廓和内容。

    检测碰撞的方式:

    • 检查矩形是否重叠。否则,就不可能发生碰撞。
    • 否则,创建一个对象编号为 1 的矩形,其中包含它的掩码。
    • 构造对象 2 的另一个矩形,其中包含它的掩码。
    • 按位与矩形 2 与矩形 1 的重叠部分。
    • 如果矩形 1 中还有 1 位,则说明发生冲突。

    这会考虑到“几乎未命中”,即每个对象的边界矩形重叠,但不一定是对象自身的轮廓。位运算符是检测这一点的有效方法。

    这是一个箭头没有完全击中气球的示例 - 在我的图形设计技能面前颤抖:

    ....xx....
    ..xx..xx..
    .x......x.
    .x......x.
    x........x
    x........x
    .x......x.
    .x......x.
    ..xx..xx..
    ....xx.**y.....
           .y......
           yyyyyyyy
           .y......
           ..y.....
    

    您可以看到,即使矩形重叠(请参阅**y),箭头实际上并没有与气球接触。通过对掩码应用按位与运算,这些位最终将为零,从而导致不冲突。


    @kyoryu 在他的评论中提出了一个有趣的观点。一些游戏很好地适应了由较小的矩形组成的对象,您可以简化基于矩形组件的碰撞检测(无需担心像素完美)。例如,我们的老朋友太空侵略者(实际上是那个游戏中对抗太空侵略者的防御者)可能由两个矩形组成,X 和 Y,导弹由 Z 组成:

        YYYY                .Z.
        YYYY                .Z.
    XXXXXXXXXXXX            .Z.
    XXXXXXXXXXXX            ZZZ
    XXXXXXXXXXXX            .Z.
    XXXXXXXXXXXX
    

    这将归结为导弹与两个太空入侵者矩形的简单矩形检查 - 考虑到导弹的大小,即使您接触到 . 字符之一(考虑它们),您也可能将其称为碰撞近程导弹,而不是冲击型导弹)。

    【讨论】:

    • 通常情况下,对于这样的游戏,您只需要矩形即可。大多数街机类型的游戏只使用矩形,实际上使用的矩形不一定与它们所代表的东西大小相同(通常对玩家来说更小,而对敌人来说则更大)。几乎从不需要每像素精度。
    • 好点,@kyoryu,但即使是最简单的游戏也会有由 多个 矩形组成的对象(否则图形会很糟糕)。这些规则仍然有效,只是不是检测像素碰撞(逻辑结束位置),而是检测构成对象的矩形之间的碰撞。所示的球示例由于其弯曲特性,不适合矩形。
    • 通常精灵的渲染和碰撞不会 1:1 映射。虽然渲染了任意详细的精灵,但在大多数 2d 游戏中,碰撞是针对单个盒子完成的,该盒子通常比精灵小。 Sprite = 复杂图像,碰撞 = 单个矩形。
    【解决方案2】:

    对于像这样的简单游戏,我发现使用圆圈可以很容易地检测碰撞。我们可以使用Pythagorean Theorem for triangles

    c^2 = a^2 + b^2
    

    我们可以通过知道如果中心之间的距离小于它们必须碰撞的组合半径来检测两个圆之间的碰撞,对吗?然后您可以像这样进行碰撞检查:

    distX ^ 2 + distY ^ 2 <= (radius1 + radious2) ^ 2 == COLLISION!
    

    distX 和 distY 是两个圆的中心之间的距离,除非圆的大小发生变化,否则可以预先计算半径 1 + 半径 2 的平方。

    使用圆形的好处是计算对象如何相互反弹也比使用正方形或矩形要容易得多。

    【讨论】:

      【解决方案3】:

      与盒子发生碰撞很容易。如果你只看 x 轴,两个盒子有三种可能的排列方式:

      1. 重叠
      2. 第一个框在第二个框的左侧
      3. 第一个框位于第二个框的右侧。

      如果第一个盒子在第二个盒子的左边,这意味着它的最右边的点必须在第二个盒子最左边的点的左边。

      first.right < second.left
      

      如果第一个盒子在第二个盒子的右边,它的最左边点必须在第二个盒子最右边点的右边。

      first.left > second.right
      

      如果这些都不成立,则框会在 x 轴上重叠。

      然后,您可以对 y 平面重复此操作(用顶部和底部代替左右),以确定框是否也在 y 轴上重叠 - 如果重叠,则它们正在碰撞!这就是 2d 游戏中简单碰撞所需要做的全部事情。

      可能会出现更大的问题,具体取决于您拥有多少不同的对象,因为碰撞检测的简单实现是 O(N^2) 算法。

      【讨论】:

      • 我试过了,但还是不行……我需要对正在移动的方形图像进行碰撞检测……如果你有示例代码,请给我或者如果你有相关链接对于示例代码,也请给我...
      【解决方案4】:

      检测两个图像的 X 和 Y,然后进行一些计算,如果它们的大小不同,则减去每个图像的宽度和高度,以获得正确的 x 和 y 坐标。 示例:

      |------- | | | | | | |_______| ` | | | | 下来 |----------| | | | | | | |----------| 减去宽度和高度以找出正确的 x 和 y

      【讨论】:

        【解决方案5】:

        如果您愿意,JBox2D 是一个了不起的物理引擎,旨在帮助解决这个问题。它会为您处理所有物理问题,您所要做的就是在它告诉您的位置绘制图像。

        我个人现在一直在使用它。我确实觉得开始使用有点困难,但是一旦你开始记住如何制作一个对象,它就会变得非常容易。

        你可以下载它here

        还有一些关于基础知识的视频here。他使用的库有点“如意算盘”,但您可以轻松理解基础知识。

        【讨论】:

          【解决方案6】:

          您可以使用 Java 内置的矩形交集。它甚至适用于旋转的矩形。

          1. 创建矩形并确保它跟随对象的旋转和位置。

          2. 每帧调用它的rectangle.intersects(Rectangle)方法,看看它是否相交。

          使用多个矩形可以为奇怪形状的图像创建更好的命中框。

          【讨论】:

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