1

所以我用javascript和canvas创建了一个沙子模拟。

我的第一个方法是用一个和值array填充。每个物体代表一粒沙子。objectsxy

这种方法在大画布上有效,但在约 600 粒后开始放慢速度。

我的下一个方法是一个二维矩阵,其中每个index都是01。它在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);
};
4

2 回答 2

0

您基本上需要使用不同的数据结构。我创建了类似的东西(康威生命游戏的 MMO 版本),它使用一块大小的板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);
};
于 2012-08-12T15:27:34.323 回答
0

首先,我会使用 Chrome 的开发者工具来分析您的应用程序并找出您的瓶颈所在。

如果碰撞检测算法随着对象数量的增加而减慢修复速度,您可以实现四叉树以减少比较次数。有关 javascript 实现,请参见此处

于 2012-08-14T06:42:26.297 回答