我正在创建一个基于 Node.js/WebGL/Canvas/PIXI.js 的视频游戏。
在此游戏中, block 具有通用尺寸:它们可以是圆形、多边形或任何形状。因此,我的物理引擎需要知道物体到底在哪里,哪些像素是墙壁,哪些像素不是。因为我认为 PIXI 不允许这样做,所以我创建了一个不可见的 Canvas ,将 map 的所有墙壁图像放置在其中。然后,我使用函数 getImageData 在 (x, y) 处创建函数“isWall”:
function isWall(x, y):
return canvas.getImageData(x, y, 1, 1).data[3] != 0;
但是,这非常慢(根据 Chrome 分析,它占用了游戏 70% 的 CPU 时间)。另外,由于我引入了此功能,有时我会收到错误“哎呀,WebGL 崩溃了”,而没有任何其他建议。
有没有更好的方法来访问像素的值?我考虑过将所有内容存储在静态位数组中(墙壁具有固定大小),其中 1 对应于墙壁,0 对应于非墙壁。内存中存在 1000 万个单元的数组是否合理?
最佳答案
一些想法:
- 第一次检查:对所有对象使用碰撞区域。甚至可以根据形状(即复杂形状)为每一侧定义区域。仅检查相交区域内的碰撞。
- 对 HitTest 位图使用一半分辨率(如果您的场景允许,甚至可以使用 25%)。当物体移动时,我们的大脑无法检测到像素精确的碰撞,因此可以利用这一点。
- 对于复杂形状,预存储其整个位图(基于其区域),但将其转换为单值类型数组,例如 Uint8Array高值和低值(重复使用它而不是通过上下文获取一和一像素)。减去对象的位置并将结果用作形状区域的增量,然后对“位图”进行 HitTest 。如果形状旋转,则相应地变换传入的检查点(这里可能有一个最佳点,其中更新位图比变换一堆点等更快。您需要测试您的场景)。
- 对于接近正方形的物体,请做出折衷并使用简单的矩形检查
- 对于圆形和椭圆形,使用非平方值来检查半径距离。
- 在某些情况下,您也许可以使用在游戏开始之前以及在了解所有物体位置、方向和速度时计算的碰撞预测(计算完整的运动路径,找到这些路径的交点,计算到这些交叉路口的时间/距离)。如果您的对象由于其路径中的其他事件而改变方向等,这当然不会很好地工作(或者尝试看看重新计算是否有益)。
我确信为什么你需要 10m 存储在内存中,虽然这是可行的 - 但你需要使用四叉树之类的东西并将数组分开,这样查找像素状态就变得高效。在我看来,您只需要存储复杂形状的“位”,并且可以通过为每个形状定义多个区域来进一步限制它。对于更简单的形状,只需使用矢量(矩形、半径/距离)。经常进行性能测试以找到适当的平衡。
无论如何 - 此类事情必须针对特定场景进行手动优化,因此这只是一般情况。其他因素也会影响该方法,例如高速、旋转、反射等,并且它很快就会变得非常广泛。希望这能提供一些意见。
关于javascript - JS Canvas 获取像素值非常频繁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28468202/