Java游戏中的碰撞检测?

3

我正在开发一款游戏,其中遇到了移动图像的碰撞检测问题。这个游戏有一个宇宙飞船和若干个小行星(障碍物)。我想要检测它们之间的碰撞。我该怎么做呢?

6个回答

15

除了矩形之外,一般来说,检测碰撞是很棘手的。

我过去处理这个问题的方式是为每个对象提供图像和掩码。例如,像迷失太空中的木星2号宇宙飞船这样的对象将具有以下图像和掩码:

     X            00000100000
  XXXXXXX         00111111100
 X       X        01111111110
X         X       11111111111
 X       X        01111111110
  XXXXXXX         00111111100
    XXX           00001110000
< p > Image 是显示在屏幕上的内容,但是掩码是用于碰撞检测的。您会注意到掩码中的1基本上是图像的轮廓和内容。

检测碰撞的方法:

  • 检查矩形是否重叠。如果没有,则不可能发生碰撞。
  • 否则,创建一个由其掩码组成的对象1的矩形。
  • 构造另一个由其掩码组成的对象2的矩形。
  • 对矩形2的重叠部分与矩形1进行按位AND运算。
  • 如果矩形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),箭头也没有实际接触气球。将按位 AND 操作应用于掩码,这些位最终会变为零,导致无碰撞。


在他的评论中,@kyoryu提出了一个有趣的观点。一些游戏适合使用由较小矩形组成的对象,并且您可以根据矩形组件简化碰撞检测(而不必担心像素完美)。例如,我们的老朋友太空入侵者(实际上是该游戏中太空入侵者的防御者)可能由两个矩形X和Y组成,导弹由Z制成:

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

这将涉及对导弹与两个太空入侵者矩形的简单矩形检查 - 鉴于导弹的大小,即使接触到一个字符(将其视为接近导弹而不是撞击类型),您也可以称之为碰撞。

1
通常,对于像这样的游戏,你只需要使用矩形。大多数街机类型的游戏只使用矩形,并且实际上使用的矩形不一定与它们所代表的物体大小相同(通常玩家的矩形较小,敌人的矩形较大)。几乎从不需要像素级的精度。 - kyoryu
好观点,@kyoryu,但是即使是最简单的游戏也会有由多个矩形组成的对象(否则图形会非常糟糕)。这些规则仍然适用,只是你不是检测像素碰撞(逻辑终点),而是检测构成一个对象的矩形之间的碰撞。所示的球示例由于其曲线特性不适合矩形。 - paxdiablo
通常,在精灵的渲染和碰撞检测之间没有一一对应关系。在大多数二维游戏中,尽管精灵可能非常复杂,但是碰撞检测只针对一个单独的矩形框进行,而这个矩形框通常比精灵小。精灵=复杂图像,碰撞检测=单一矩形。 - kyoryu

1

对于像这样简单的游戏,我发现使用圆形可以很容易地检测到碰撞。我们可以利用勾股定理来处理三角形。

c^2 = a^2 + b^2

我们可以通过知道两个圆心之间的距离是否小于它们的半径之和来检测两个圆之间的碰撞,对吧?然后你可以像这样进行碰撞检查:
distX ^ 2 + distY ^ 2 <= (radius1 + radious2) ^ 2 == COLLISION!

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

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


1

用盒子进行碰撞检测非常容易。如果仅查看x轴,两个盒子可能有三种排列方式:

  1. 重叠
  2. 第一个盒子在第二个盒子左侧
  3. 第一个盒子在第二个盒子右侧。

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

first.right < second.left

如果第一个框在第二个框的右侧,则其最左侧点必须在第二个框的最右侧点的右侧。
first.left > second.right

如果上述条件都不满足,则说明盒子在X轴上重叠。

接着,在Y平面上进行类似的操作(用上下替代左右),以找出盒子是否也在Y轴上发生重叠 - 如果是,则它们正在碰撞!这基本上是你在二维游戏中所需做的全部内容。

更大的问题可能会出现在你拥有多少不同的对象上,因为碰撞检测的天真实现是O(N ^ 2)算法。


我尝试过了,但仍然不起作用...... 我需要检测正在移动的正方形图像之间的碰撞。 如果您有示例代码,请提供给我;或者如果您有相关的示例代码链接,也请提供给我... - Chetan

0
检测两个图像的X和Y坐标,然后进行一些计算,如果它们的尺寸不同,则减去每个图像的宽度和高度,以获得正确的x和y坐标。 示例: |------- | | | | | | |_______|
` | | | | 向下移动
|---------| | | | | | | |---------| 减去宽度和高度以找到正确的x和y

0

如果您愿意这样做,JBox2D是一个令人惊叹的物理引擎,旨在帮助解决这个问题。它为您处理所有的物理问题,您所要做的就是在它告诉您的地方绘制图像。

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

您可以在这里下载它。

还有一些关于基础知识的视频在这里。他使用的库有点“含糊不清”,但您可以轻松理解基础知识。


0

你可以使用Java内置的矩形相交功能,即使是旋转的矩形也适用。

  1. 创建矩形并确保其遵循对象的旋转和位置。

  2. 每帧调用rectangle.intersects(Rectangle)方法来查找是否相交。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接