Java游戏中的碰撞检测?

我正在开发一种游戏,其中我有运动图像的碰撞检测问题。 游戏中有一个宇宙飞船和数量的小行星(障碍物)。 我想检测它们之间的碰撞。 我怎样才能做到这一点?

对于除矩形之外的任何事物,碰撞检测通常都很棘手。

我过去这样做的方法是为每个对象提供图像和掩码。 因此,例如,像Lost in Space中的Jupiter 2太空船这样的物体将具有以下图像和掩模:

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

图像是被屏幕划分的,但是掩模是用于碰撞检测的。 您会注意到蒙版中的1基本上是图像的轮廓和内容。

检测碰撞的方式:

  • 检查矩形是否重叠。 如果没有,就不会发生碰撞。
  • 否则,创建一个由其掩码组成的对象编号1的矩形。
  • 构造另一个由其掩码组成的对象2矩形。
  • 按位-AND矩形2与矩形1的重叠部分。
  • 如果矩形1中还有1位,则表示发生了碰撞。

这考虑了“接近未命中”,其中每个对象的边界矩形重叠但不一定是对象轮廓本身。 按位运算符是检测此问题的有效方法。

这是一个箭头没有碰到气球的例子 – 在我的图形设计技巧之前颤抖:

 ....xx.... ..xx..xx.. .x......x. .x......xx.......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 

这可以归结为对两个太空入侵者矩形的导弹的简单矩形检查 – 考虑到导弹的大小,即使你联系其中一个导弹,你也可能把它称为碰撞. 角色(考虑它们是近距离导弹而不是撞击变形导弹)。

对于像这样的简单游戏,我发现使用圆圈可以非常容易地检测碰撞。 我们可以将毕达哥拉斯定理用于三角形

 c^2 = a^2 + b^2 

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

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

distX和distY是两个圆的中心之间的距离,并且除非圆的大小正在改变,否则可以预先计算radius1 + radius2的平方。

使用圆形的一个好处是计算物体彼此反弹的方式也比使用方形或矩形更容易。

与箱子碰撞很容易。 如果你只看x轴,那么两个盒子有三种可能的安排:

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

如果第一个框位于第二个框的左侧,则表示其最右边的点必须位于第二个框的最左边点的左侧。

 first.right < second.left 

如果第一个框位于第二个框的右侧,则其最左侧的点必须位于第二个框的最右侧点的右侧。

 first.left > second.right 

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

然后,您可以对y平面重复此操作(替换左侧和右侧的顶部和底部),以确定框是否也在y轴上重叠 - 如果它们相同,则它们会发生碰撞! 对于2D游戏中的简单碰撞,这就是你真正需要做的。

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

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

 | -------
 |  |
 |  |
 |  |
 | _______ |

 `|
     |
     |
     |
降临



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


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

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

你可以在这里下载。

这里还有一些关于基础知识的video。 他使用的图书馆有点“愚蠢”,但你可以很容易地理解基础知识。

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

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

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

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