弹球游戏的2D碰撞检测


9

到目前为止,在以前的游戏中,我使用带有框的简单2D碰撞,然后在像素级别检查碰撞。

如果要在几乎很多帧中进行弹球游戏,那么球将与墙壁或其他表面接触,那么还有其他方法吗?

Answers:


19

早在1990年,旧的弹球游戏就是这样制作的:

游戏场有几层(玩游戏时会看到什么):

在此处输入图片说明

和几层碰撞:

在此处输入图片说明 在此处输入图片说明

左图是主游戏的碰撞图,右图是特殊区域(弹球坡道)的碰撞图。

White =球的自由区域,颜色索引为255。

Gray=球将被“推离”该区域。颜色索引=要添加到球位置的矢量角度。浅灰色= 0度。深灰色= 360度

一些伪代码:

void do_ball_physics()
{
    while(1)
    {
         byte color = read_pixel_under_ball(ballx, bally); //one pixel read
         if(color == 255) //see remark below
            break;
         float vectorx = sin(color/255.0f * 2.0f * PI);
         float vectory = cos(color/255.0f * 2.0f * PI); 
         ballx += vectorx; //push ball away from one unit
         bally += vectory; //

    }
}

一些特殊的颜色索引,也可以使用的东西比其他碰撞,自定义颜色范围(例如:240 - 255)可以保留用于检测之类的特殊区域spinnerstriggersbumpersholes,...

如您所见,这非常简单。每帧只有几个像素“读取”。因此,您可以使物理模拟以真正的高帧频运行,例如:200 fps。使用高帧速率将使模拟平滑并减少“隧道效应”(当球运动太快并通过槽元素而不会发生碰撞时,会发生这种情况)。这种简单性还使过去可以386 computers(甚至快速286)进行流畅的弹球游戏(在其他一些技巧中,例如颜色循环,vga滚动和精灵遮罩...)。

如今,大多数弹球游戏不再像这样制作。相反,运动场是使用多边形或精灵的2d / 3d场景,并且与一些简化的线,贝塞尔曲线或代表可视化运动场的简化形状的球体发生了碰撞。

示例(来自视觉弹球):

在此处输入图片说明

一些游戏公司使用自己的物理引擎,而另一种更简单的方法是使用物理引擎,例如Box2DBullet。我看到的大多数iPhone弹球游戏都使用了预先存在的物理引擎+一些3D资产。


...我们在这里谈论的是javascript和canvas,因此在此框架中,最慢的操作是...绘制和读取像素...尤其是在最慢的设备上。因此,这个答案的4/5只是历史记录/无关紧要。但是比率不能与图片竞争。
GameAlchemist 2012年

1
碰撞图可以存储在数组中,为什么还要将它们存储在某些画布中?正如您所说,答案的第一部分主要是针对历史的,但是如果您需要在非常低端的cpu(例如,旧的gsm)上实现弹球,则仍然适用。在现代,我宁愿建议使用jbox2d之类的物理引擎,也可以自己对线段或贝塞尔曲线进行碰撞(如果您认为自己可以写这样的东西)来进行物理处理。
tigrou 2012年

在现代浏览器中,读取图像中的像素也非常快。一些最初的“ omg JS比C更快”的演示都是图像处理内核。
肖恩·米德迪奇

您是如何了解碰撞图的?
Bemmu

1
由于这个弹球梦,重制了:pouet.net/prod.php?哪个= 24499(不是我本人)。看一下源代码,我谈论的碰撞图在那里。
tigrou

1

弹球的物理性质非常丰富,不仅有球洞或墙壁,而且还有反应元素(向后击打)或不平坦的表面(球变慢然后恢复速度)。

如果要创建一个好的弹球,方法是使用3D碰撞检测,或者对每个可碰撞对象使用具有距离和速度参数的方法的自定义系统,并返回变化的速度。


为什么说3D碰撞检测比2D有什么优势?
John

@John我想像一个不错的弹球游戏,它可以作为带有坡道等的3D游戏。您可以在2D中对这些坡道进行编程,并在坡道超过坡道时放大球,而当坡道落回自己时则降低球,但在这种情况下,它仍然是3D游戏中,您只需自己添加Z尺寸。
Markus von Broady,2012年

1

我前一段时间做了一场弹球游戏;它也是基于像素的。我有一个碰撞图,其中仅包含碰撞数据。近似的碰撞法线很容易找到:

取与球重叠的碰撞图区域,找到中心,形成从该点到球中心的矢量,然后进行归一化。

希望能给你一些想法:)


1

首先,如果您制作弹球游戏,则比包围盒更可能需要更多的边界碰撞检测:-)
考虑到成熟的弹球涉及的物理复杂性,我建议您看一下现有的2D物理引擎。Box2D在javascript方面颇有声誉,也许还有其他人,但是我没有遇到任何好的(免费)的。
Rq1:您当然可以(像我一样)在游戏的更新和平局之间使用经典分割。然后,您使用计时器(setInterval / setTimeout)和/或RequestAnimationFrame调用更新,然后以常规方式绘制。弹子球可能是您想要一次更新计时器而另一次进行平局的游戏类型,因此您可以独立调整每种比率,以在多种设备上工作。因为如果设备太慢,您不能仅仅放弃(更新+绘制):如果两次更新(dt)之间的时间太长,则物理引擎可能会错过碰撞。


0

您可能会看看2D与3D主题的视觉弹球与未来弹球。如果您玩视觉弹球游戏(所有东西都是2d制),然后再玩未来的弹球游戏,或者像Zen Pinball之类的东西,您确实会感觉到它们的玩法有所不同。我个人更喜欢3d,但是您的项目可能更适合2d,只有您才能决定

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.