1

そこで、javascriptとcanvasを使用して砂のシミュレーションを作成しました。

私の最初のアプローチは、との価値でarray満たされていました。各オブジェクトは砂粒を表しています。objectsxy

この方法は大きなキャンバスで機能しましたが、約600グレイン後に速度が低下し始めました。

index私の次のアプローチは、それぞれがまたはのいずれか0である2次元行列でした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);
};
4

2 に答える 2

0

まず、Chrome の開発者ツールを使用してアプリのプロファイルを作成し、正確にボトルネックを特定します。

オブジェクトの数が増えると衝突検出アルゴリズムの修正が遅くなる場合は、Quad Tree を実装して比較の数を減らすことができます。JavaScript の実装については、こちらを参照してください。

于 2012-08-14T06:42:26.297 に答える
0

基本的に、別のデータ構造を使用する必要があります。私は似たようなもの (コンウェイのライフ ゲームの MMO バージョン) を作成しました。これは、サイズのボードを使用します2 ^ 106(私が間違っていなければ、ほぼ 80 千兆セルです)。

秘訣は、生細胞の座標のみを (ベクトルの形式で) 保存することです。生きているセルの数は死んだセルの数よりもはるかに少ないため、使用するスペースは非常に少なくなります。

また、砂粒を座標ベクトルとして保存するため、ループ内でxandを計算する必要がないという利点もあります。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 に答える