所以我用javascript和canvas创建了一个沙子模拟。
我的第一种方法是array
填充objects
,其值x
和y
。
每个物体代表一粒沙子。
这种方法适用于大型帆布,但在约600粒后开始减速。
我的下一个方法是二维矩阵,其中每个index
都是0
或1
。
它在200 x 200
画布上工作正常,但随着画布大小的增加,它变得太慢了。
..这是合理的,因为例如800 x 600
画布的长度为480k
。
所以我的问题是,如何优化这样的事情?
如果您需要,可以使用以下代码:
var draw = function() {
if (MOUSE_DOWN) { cast_grains(); }
for (var i = matrix.length; i > 0; i--) {
if (matrix[i] == "1") {
var x = i % canvas.width;
var y = Math.floor(i / canvas.width);
bfr.fillStyle = "#000";
bfr.fillRect(x, y, 1, 1);
/* ... movement calculation ... */
bfr.fillStyle = "rgb(255, 255, 200)";
bfr.fillRect(x, y, 1, 1);
}
}
ctx.drawImage(buffer, 0, 0);
};
答案 0 :(得分:0)
您基本上需要使用不同的数据结构。我创建了类似的东西(an MMO version of Conway's Game of Life),它使用了一块大小为2 ^ 106
的板子(如果我没弄错的话,它将近80万亿千万亿个单元)。
诀窍是只存储活细胞的坐标(以向量的形式)。由于活细胞的数量远远少于死细胞的数量,因此最终只占用很少的空间。
由于您将沙粒存储为坐标向量,因此您还可以不需要在循环中计算x
和y
。你的功能看起来像:
var draw = function() {
if (MOUSE_DOWN) { cast_grains(); }
for (var i = grains.length - 1; i >= 0; i--) {
var x = grains[i][0];
var y = grains[i][1];
bfr.fillStyle = "#000";
bfr.fillRect(x, y, 1, 1);
/* ... movement calculation ... */
bfr.fillStyle = "rgb(255, 255, 200)";
bfr.fillRect(x, y, 1, 1);
}
ctx.drawImage(buffer, 0, 0);
};
答案 1 :(得分:0)
首先,我会使用Chrome的开发者工具来分析您的应用,并找出究竟是什么的瓶颈。
如果碰撞检测算法随着对象数量的增加而减慢修复,则可以实现四叉树以减少比较次数。有关javascript实现,请参阅here。