我正在用 javascript canvas 编写游戏,有时我会遇到延迟。我认为这是因为我在画布上画了很多东西。
例如,我的背景不是静态的,它从右向左移动,所以每次我都必须清除整个画布。而且我不是只用一种颜色来清除,而是用一个移动游戏循环的每个循环的图像来清除。
我认为这是一个昂贵的操作,我在想是否有什么东西可以降低这个操作的成本,例如使用双缓冲来清除背景(不知道你是否可以使用双缓冲来清除背景?)。
还是应该在整个游戏中使用双缓冲?(我不这么认为,因为我已经读过浏览器已经为您做到了)
我正在用 javascript canvas 编写游戏,有时我会遇到延迟。我认为这是因为我在画布上画了很多东西。
例如,我的背景不是静态的,它从右向左移动,所以每次我都必须清除整个画布。而且我不是只用一种颜色来清除,而是用一个移动游戏循环的每个循环的图像来清除。
我认为这是一个昂贵的操作,我在想是否有什么东西可以降低这个操作的成本,例如使用双缓冲来清除背景(不知道你是否可以使用双缓冲来清除背景?)。
还是应该在整个游戏中使用双缓冲?(我不这么认为,因为我已经读过浏览器已经为您做到了)
由于您“有时”会遇到延迟,而且这不是低帧率问题,我宁愿将目光转向邪恶的垃圾收集器:每当它触发时,应用程序将冻结长达几毫秒,你会得到一帧未命中。
要注意这一点,您可以使用谷歌分析工具,在 TimeLine / Memory / 按下记录按钮:您可以看到当使用的内存突然下降时发生了 GC。
使用此工具时请注意,它会降低应用程序的速度,并且会自行创建垃圾(!)...
此外,由于任何函数调用都会产生一些垃圾,因此您无法获得完整的平坦的记忆线。
下面我展示了我在优化内存使用之前
制作的一个简单游戏的图表,
每秒最多 5 GC:
这里是内存优化后的同一个游戏的图表:每秒 1 GC。由于我上面提到的限制,它实际上是我们能得到的最好的,并且游戏没有丢帧并且感觉更灵敏。
为了避免产生垃圾
- 永远不要创建对象、数组或函数。
- 永远不要增加或减少数组大小。
- 注意隐藏对象的创建:Function.bind 或 Array.splice 是两个例子。
您还可以:
- 池(回收)您的对象 - 使用粒子引擎来处理大量/短暂的对象。
我制作了一个池化库(此处)和一个粒子引擎(此处),如果您有兴趣可以使用。
但也许首先要做的是寻找创建对象的位置,并且只创建一次。由于 js 是单线程的,因此您实际上可以在很多事情上使用静态对象而没有任何风险。
只是一个小解释:
function complicatedComputation(parameters) {
// ...
var x=parameters.x, y = parameters.y, ... ...
}
// you can call creating an object each time :
var res = complicatedComputation ( { x : this.x, y : this.y, ... ... } );
//... or for instance define once a parameter object :
complicatedComputation.parameters = { x :0, y:0, ... ... };
// then when you want to call :
var params = complicatedComputation.parameters;
params.x = this.x ; params.y = this.y; ... ...
var res = complicatedComputation(params);
它的缺点是之前的调用参数仍然存在,所以如果你不
设置它们,你就不会得到未定义,而是之前的值,所以你可能不得不改变你的函数。
但另一方面,如果你多次调用具有相似参数的函数,它就会非常方便。
快乐的记忆狩猎!
双缓冲是一种减少闪烁的技术:您在显示另一个缓冲区的同时绘制到一个缓冲区,然后在一次操作中将它们交换出来,因此用户看不到任何处于部分状态的绘图。
但是,它对于性能问题并没有真正的帮助,因为仍然有相同数量的绘图。如果您没有闪烁问题,我不会尝试使用双缓冲,因为它需要更多内存,并且系统可能会通过类似或其他方式隐式阻止闪烁。
如果您认为绘制背景太昂贵,您可以考虑以下几点:
绘图时是否按比例缩小背景图像?如果是这样,请创建一次缩小版本并使用它来清除背景,从而降低每次迭代的绘图成本。
记住“脏”区域,只画出被遮挡的背景部分。这将增加一些管理开销,但会显着减少需要触摸的像素数量
使背景成为画布 DOM 元素的背景图像,并在每次迭代中将画布清除为透明。如果画布非常大,您可以通过记住“脏”区域并清除它们来加快速度。
您确定绘制背景是延迟的主要原因吗?当您只重绘背景而没有做很多其他事情时,您是否还有延迟?