[英]Pixel Perfect Collision Detection in HTML5 Canvas
我想检查HTML5画布中两个Sprite之间的碰撞。 因此,为了讨论,让我们假设两个精灵都是IMG对象,并且碰撞意味着alpha通道不是0.现在这两个精灵都可以围绕对象的中心旋转,但是如果这样做则没有其他变换更容易。
现在,我想出的明显解决方案是:
我看到的问题是:a)JavaScript中没有矩阵类,这意味着我必须在JavaScript中这样做,这可能非常慢,我必须测试每帧的冲突,这使得它非常昂贵。 此外,我必须复制我在绘图时必须做的事情(或者画布对我来说,设置矩阵)。
我想知道我在这里是否遗漏了什么,以及是否有更容易的碰撞检测解决方案。
我不是一个javascript编码器,但我认为相同的优化技巧对于Javascript和C ++一样有效。
只需旋转精灵的角落而不是每个像素。 实际上,你会做一些像软件纹理映射的事情。 您可以使用各种梯度信息计算出给定像素的x,y位置。 查找软件纹理映射以获取更多信息。
如果您将四元组分解为“命中”和“非命中”区域,那么您可以有效地检查给定的四元树分解是否全部为“未命中”,“全部命中”或“可能命中”(即包含命中和非命中像素。前两个是很容易通过的。在最后一种情况下,你可以进入下一个分解级别并重复测试。这样你只需检查你需要的像素和大面积的“非击中“和”命中“你不必做这么复杂的检查。
无论如何这只是一些想法。
我必须复制我在绘图时必须做的事情
好吧,您可以创建一个新的渲染上下文,将一个旋转的白色背景遮罩绘制到它上面,将合成操作设置为lighter
亮,并将给定偏移处的另一个旋转遮罩绘制在顶部。
现在,如果剩下非白色像素,则会有一个点击。 你仍然需要getImageData
并筛选像素才能找到它。 您可以通过向下缩放结果图像来减少该工作量(依靠抗锯齿来保持一些像素非白色),但我认为它可能仍然会很慢。
我必须测试每帧的碰撞,这使得它非常昂贵。
是的,我认为你将会使用预先计算的碰撞表。 如果你有足够的空间,你可以为精灵a,精灵b,相对旋转,相对-x-标准化 - 旋转和相对-γ-标准化 - 旋转的每个组合存储一个命中/不命中位。 。 根据您拥有的精灵数量以及旋转或移动的步数,这可能会变得相当大。
一个折衷是存储每个子画面的一个JavaScript阵列中的旋转的前面罩(数目,给你32个比特/容易像素&&
-able数据,或如在SRING一个字符,给你16位)和&&
交叉精灵的每一行掩盖在一起。
或者,放弃像素并开始查看例如。 路径。
同样的问题,另一种解决方案。 首先,我使用getImageData数据来查找围绕精灵的多边形。 这里要小心,因为实现适用于具有透明背景且具有单个实体对象的图像。 就像一艘船。 下一步是Ramer Douglas Peucker算法减少多边形中顶点的数量。 我终于得到了一个非常少的顶点的多边形,旋转方便且便宜,并检查每个精灵与其他多边形的碰撞。
http://jsfiddle.net/rnrlabs/9dxSg/
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = document.getElementById("img");
context.drawImage(img, 0,0);
var dat = context.getImageData(0,0,img.width, img.height);
// see jsfiddle
var startPixel = findStartPixel(dat, 0);
var path = followPath(startPixel, dat, 0);
// 4 is RDP epsilon
map1 = properRDP(path.map, 4, path.startpixel.x, path.startpixel.y);
// draw
context.beginPath();
context.moveTo(path.startpixel.x, path.startpixel.x);
for(var i = 0; i < map.length; i++) {
var p = map[i];
context.lineTo(p.x, p.y);
}
context.strokeStyle = 'red';
context.closePath();
context.stroke();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.