HTML5 Canvas 碰撞检测“globalCompositeOperation”表现
早上好,
在过去的几个月里,我一直在修改 HTML5 Canvas API,并且从中获得了很多乐趣。
我逐渐创建了一些小游戏,纯粹是为了自学游戏开发的注意事项。我现在能够进行基本的碰撞检测,即圆和平台之间的碰撞(对于大多数人来说相当简单,但当你第一次让它工作时,感觉就像是一个相当大的成就,当你了解什么时,效果会更好实际上正在发生)。我知道像素碰撞检测并不适用于所有游戏,纯粹是因为在许多情况下,您可以使用上面讨论的方法获得足够好的结果,并且这种方法显然在资源上相当昂贵。
但我只是灵机一动(很可能其他人也想到了这一点,而我已经深入研究这个领域,但我用谷歌搜索了一下,却什么也没找到)……所以这里……
有可能吗?使用/利用画布的“globalCompositeOperation”功能。我最初的想法是将其方法设置为“xor”,然后检查画布上的所有像素的透明度,如果找到像素则必定发生碰撞。正确的?显然,此时您需要弄清楚相关像素被哪些对象占用以及如何反应,但对于其他其他技术,您必须这样做。
是说画布已经在幕后进行碰撞检测,以便计算出形状何时重叠?是否可以对此进行扩展?
有什么想法吗?
加里
Morning,
Over the past few months I have been tinkering with the HTML5 Canvas API and have had quite a lot of fun doing so.
I've gradually created a number of small games purely for teaching myself the do's and don'ts of game development. I am at a point where I am able to carry out basic collision detection, i.e. collisions between circles and platforms (fairly simple for most out there but it felt like quite an achievement when you first get it working, and even better when you understand what is actually going on). I know pixel collision detection is not for every game purely because in many scenarios you can achieve good enough results using the methods discussed above and this method is obviously quite expensive on resources.
But I just had a brainwave (It is more than likely somebody else has thought of this and I am way down the field but I've googled it and found nothing)....so here goes....
Would it possible to use/harness the "globalCompositeOperation" feature of canvas. My initial thoughts were to set its method to "xor" and then check the all pixels on the canvas for transparency, if a pixel is found there must be a collision. Right? Obviously at this point you need to work out which objects the pixel in question is occupied by and how to react but you would have to do this for other other techniques.
Saying that is the canvas already doing this collision detection behind the scenes in order to work out when shapes are overlapping? Would it be possible to extend upon this?
Any ideas?
Gary
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
画布不会自动执行此操作(可能是因为它仍处于起步阶段)。 easeljs 对鼠标进入/离开事件采用这种方法,而且效率极低。我正在使用算法方法来确定边界。然后我用它来查看鼠标是在形状的内部还是外部。理论上,要以这种方式实现命中检测,您所要做的就是获取两个形状的所有点,并查看它们是否处于其他形状。如果您想查看我的一些代码,请告诉我
但是,我会说,虽然您的方法效率很低,但它全局适用于任何形状。
The canvas doesn't do this automatically (probably b/c it is still in its infancy). easeljs takes this approach for mouse enter/leave events, and it is extremely inefficient. I am using an algorithmic approach to determining bounds. I then use that to see if the mouse is inside or outside of the shape. In theory, to implement hit detection this way, all you have to do is take all the points of both shapes, and see if they are ever in the other shape. If you want to see some of my code, just let me know
However, I will say that, although your way is very inefficient, it is globally applicable to any shape.
我在 codepen 上做了一个演示,它使用离屏画布进行碰撞检测,并将
globalCompositeOperation
设置为xor
正如您提到的。代码简短,并且对于较小的“碰撞画布”应该具有良好的性能。http://codepen.io/sakri/pen/nIiBq
I made a demo on codepen which does the collision detection using an off screen canvas with
globalCompositeOperation
set toxor
as you mentioned. The code is short and simple, and should have OK performance with smallish "collision canvases".http://codepen.io/sakri/pen/nIiBq
如果你使用Xor模式全屏,第二步是获取屏幕的ImageData,这是一个高成本的步骤,下一步是找出哪些对象参与了碰撞。
不需要进行基准测试:它会太慢。
我建议您使用“经典”边界框测试,然后对对象的内部 BBOx 进行测试,并且仅在您本地获取像素之后进行测试。
内部边界框是指您确定完全位于对象内部的矩形,即本例中的红色部分:
因此请使用这种混合策略:
- 对对象的边界框进行测试。
- 如果 2 个 BBox 之间发生碰撞,请执行内部边界框测试:如果精灵的内部 BBox 重叠,我们确信会发生碰撞。
- 然后你只对真正有问题的情况保留像素完美测试,并且你只需要在具有较大精灵大小的临时画布上绘制两个精灵。您将能够更快地执行 getImageData。在此步骤中,您知道哪些对象参与了碰撞。
请注意,您可以在较小的画布上按比例绘制精灵,以便更快地获取 ImageData较低分辨率的成本。
一定要禁用平滑,我认为 8X8 画布应该足够了(实际上这取决于平均精灵速度。如果你的精灵很慢,请增加分辨率)。
这样数据就有 8 X 8 X 4 = 256 字节大,您可以保持良好的帧速率。
Rq 还指出,在决定如何计算内部 BBox 时,您可以允许给定数量的空像素进入该内部 BBox,以牺牲准确性来换取速度。
if you are using a Xor mode fullscreen ,the second step is to getImageData of the screen, which is a high cost step, and next step is to find out which objects were involved in the collision.
No need to benchmark : it will be too slow.
I'd suggest rather you use the 'classical' bounding box test, then a test on the inner BBOxes of objects, and only after you'd go for pixels, locally.
By inner bounding box, i mean a rectangle for which you're sure to be completely inside your object, the reddish part in this example :
So use this mixed strategy :
- do a test on the bounding boxes of your objects.
- if there's a collision in between 2 BBoxes, perform an inner bounding box test : we are sure there's a collision if the sprite's inner bboxes overlaps.
- then you keep the pixel-perfect test only for the really problematic cases, and you need only to draw both sprites on a temporary canvas that has the size of the bigger sprite. You'll be able to perform a much much faster getImageData. At this step, you know which objects are involved in the collision.
Notice that you can draw the sprites with a scale, on a smaller canvas, to get faster getImageData at the cost of a lower resolution.
Be sure to disable smoothing, and i think that already a 8X8 canvas should be enough (it depends on average sprite speed in fact. If your sprites are slow, increase the resolution).
That way the data is 8 X 8 X 4 = 256 bytes big and you can keep a good frame-rate.
Rq also that, when deciding how you compute the inner BBox, you can allow a given number of empty pixels to get into that inner BBox, trading accuracy for speed.