0

ボットが画面上を移動する jQuery でコーディングされたゲームがあります。以下のコードは 20 ミリ秒ごとに実行されるループです。現在、ボットが 15 個を超えると、ブラウザーの遅延に気付き始めます (単純に、すべての高度な衝突検出が行われているためです)。

ラグを減らす方法はありますか?もっと効率的にすることはできますか?

コードのブロックを投稿しただけで申し訳ありませんが、私の主張を十分に明確にする方法がわかりません!

$.playground().registerCallback(function(){ //Movement Loop
        if(!pause) {
            for (var i in bots) {
                //bots - color, dir, x, y, z, spawned?, spawnerid, prevd
                var self = $('#b' + i);
                var current = bots[i];
                if(bots[i][5]==1) {
                    var xspeed = 0, yspeed = 0;
                    if(current[1]==0) { yspeed = -D_SPEED; }
                    else if(current[1]==1) { xspeed = D_SPEED; }
                    else if(current[1]==2) { yspeed = D_SPEED; }
                    else if(current[1]==3) { xspeed = -D_SPEED; }

                    var x = current[2] + xspeed;
                    var y = current[3] + yspeed;
                    var z = current[3] + 120;
                    if(current[2]>0&&x>PLAYGROUND_WIDTH||current[2]<0&&x<-GRID_SIZE||
                        current[3]>0&&y>PLAYGROUND_HEIGHT||current[3]<0&&y<-GRID_SIZE) {
                            remove_bot(i, self);
                    } else {
                        if(current[7]!=current[1]) {
                            self.setAnimation(colors[current[0]][current[1]]);
                            bots[i][7] = current[1];
                        }
                        if(self.css({"left": ""+(x)+"px", "top": ""+(y)+"px", "z-index": z})) {
                            bots[i][2] = x;
                            bots[i][3] = y;
                            bots[i][4] = z;
                            bots[i][8]++;
                        }
                    }
                }
            }
            $("#debug").html(dump(arrows));
            $(".bot").each(function(){
                var b_id = $(this).attr("id").substr(1);
                var collision = false;
                var c_bot = bots[b_id];
                var b_x = c_bot[2];
                var b_y = c_bot[3];
                var b_d = c_bot[1];
                $(this).collision(".arrow,#arrows").each(function(){ //Many thanks to Selim Arsever for this fix!
                    var a_id = $(this).attr("id").substr(1);
                    var piece = arrows[a_id];
                    var a_v = piece[0];
                    if(a_v==1) {
                    var a_x = piece[2];
                    var a_y = piece[3];     
                        var d_x = b_x-a_x;
                        var d_y = b_y-a_y;
                        if(d_x>=4&&d_x<=5&&d_y>=1&&d_y<=2)  {
                            //bots - color, dir, x, y, z, spawned?, spawnerid, prevd
                            bots[b_id][7] = c_bot[1];
                            bots[b_id][1] = piece[1];   
                            collision = true;
                        }
                    }
                });
                if(!collision) {
                    $(this).collision(".wall,#level").each(function(){
                        var w_id = $(this).attr("id").substr(1);
                        var piece = pieces[w_id];
                        var w_x = piece[1];
                        var w_y = piece[2];
                        d_x = b_x-w_x;
                        d_y = b_y-w_y;
                        if(b_d==0&&d_x>=4&&d_x<=5&&d_y>=27&&d_y<=28) { kill_bot(b_id); collision = true; } //4 // 33
                        if(b_d==1&&d_x>=-12&&d_x<=-11&&d_y>=21&&d_y<=22) { kill_bot(b_id); collision = true; } //-14 // 21
                        if(b_d==2&&d_x>=4&&d_x<=5&&d_y>=-9&&d_y<=-8) { kill_bot(b_id); collision = true; } //4 // -9
                        if(b_d==3&&d_x>=22&&d_x<=23&&d_y>=20&&d_y<=21) { kill_bot(b_id); collision = true; } //22 // 21
                    });
                }
                if(!collision&&c_bot[8]>GRID_MOVE) {
                    $(this).collision(".spawn,#level").each(function(){
                        var s_id = $(this).attr("id").substr(1);
                        var piece = pieces[s_id];
                        var s_x = piece[1];
                        var s_y = piece[2];
                        d_x = b_x-s_x;
                        d_y = b_y-s_y;  
                        if(b_d==0&&d_x>=4&&d_x<=5&&d_y>=19&&d_y<=20) { kill_bot(b_id); collision = true; } //4 // 33
                        if(b_d==1&&d_x>=-14&&d_x<=-13&&d_y>=11&&d_y<=12) { kill_bot(b_id); collision = true; } //-14 // 21
                        if(b_d==2&&d_x>=4&&d_x<=5&&d_y>=-11&&d_y<=-10) { kill_bot(b_id); collision = true; } //4 // -9
                        if(b_d==3&&d_x>=22&&d_x<=23&&d_y>=11&&d_y<=12) { kill_bot(b_id); collision = true; } //22 // 21*/
                    });
                }
                if(!collision) {
                    $(this).collision(".exit,#level").each(function(){
                        var e_id = $(this).attr("id").substr(1);
                        var piece = pieces[e_id];
                        var e_x = piece[1];
                        var e_y = piece[2];
                        d_x = b_x-e_x;
                        d_y = b_y-e_y;
                        if(d_x>=4&&d_x<=5&&d_y>=1&&d_y<=2)  {
                            current_bots++;
                            bots[b_id] = false;
                            $("#current_bots").html(current_bots);
                            $("#b" + b_id).setAnimation(exit[2], function(node){$(node).fadeOut(200)});
                        }
                    });
                }
                if(!collision) {
                    $(this).collision(".bot,#level").each(function(){
                        var bd_id = $(this).attr("id").substr(1);
                        if(bd_id!=b_id) {                           
                            var piece = bots[bd_id];                                
                            var bd_x = piece[2];
                            var bd_y = piece[3];
                            d_x = b_x-bd_x;
                            d_y = b_y-bd_y;
                            if(d_x>=0&&d_x<=2&&d_y>=0&&d_y<=2) { kill_bot(b_id); kill_bot(bd_id); collision = true; }
                        }
                    });
                }
            });

        }
    }, REFRESH_RATE);

どうもありがとう、

4

2 に答える 2

4

コードを改善する方法はたくさんあります。

アルゴリズムの改善

衝突検出にはほぼ独占的にO(n 2 )アルゴリズムを使用しています。各オブジェクトに対して各ボットをテストしています。たとえば、20 個のボットと 30 個の障害物がある場合、コンピューターは(19+18+...+1) + (20*30) = 190+600 = 790衝突をテストする必要があります。

必要な衝突テストの量を減らす簡単な方法は、フィールドを小さな部分に分割することです。これを行う簡単な方法の 1 つは、並べ替えられたリストを使用することです。あなたのオブジェクトには長方形の境界があると思います。左端のソート済みリストを作成するだけです。

sorted_left_border = [40, 51, 234, 240];

使用される擬似コードは次のとおりです。

for bot in all_bots:
    left = bot.x, right = bot.x + bot.width
    top = bot.y, bottom = bot.y + bot.height
    // binary search is O(log n)
    colliding_objects = binary_search for range in sorted_left_border
    for obj in colliding_objects:
        // check the other 3 borders

4 つの境界線すべてを使用する方法はありますが、かなり複雑です。

入力がほぼソートされている場合、O(n)時間近くでソートできるソートアルゴリズムがいくつかありますが、Javascript 組み込みのソート関数を使用するだけです。(それが遅すぎる場合は、後で独自のものを書くことができます。)

DOM が遅い

ブラウザの HTML に挿入し直す前に、DOM をオフラインで更新してみてください。現在のやり方では、何かを変更するたびにブラウザーが DOM を更新する必要があります。ブラウザは、フレームごとに 1 回を超えて DOM を更新する必要はありません。

要素を DOM からプルするには、jQueryにdetachメソッドがあります。切り離された要素のみに一致する jQuery セレクターを必ず使用してください。

// remove from DOM, avoid updating it.
var theGame = $("#theGame").detach();

// select all bots and do the updating
var bots = $(".bot", theGame);

// reinsert
theGame.appendTo("body");

適切な技術の使用

DOM 要素で jQuery を使用するのは、間違った手法です。DOM はこのために構築されていません。最新のブラウザー用にのみプログラミングしている場合は、<canvas>要素の使用を検討してください。

于 2010-06-06T21:59:17.527 に答える
1

ゲオルクが説明していることは、このようなものだと思います。これはJavaアプレットであるため、JavaScriptよりも高速になりますが、原理を示しています。距離は、オブジェクトとグリッド内の隣接する 8 つの正方形内のオブジェクトの間でのみ計算されることに注意してください。これらの 8 つの正方形に他のオブジェクトがない場合、そのバブルの衝突はまったくチェックされません。

この手法はハッシュ テーブルに基づいて構築されています。すべての js オブジェクトはハッシュ テーブルであるため、javascript で実装するのはそれほど難しくありません。

于 2010-06-07T02:12:16.410 に答える