1

スニペットをキューに入れて、指定された時間(1秒に1回)にすべて実行する必要があります。スニペットは、実際には、jump()、attack()、walk('left')などのプレーヤーアクションです。

ユーザーがキーを押すと、アクションをキューに入れ、すべてのアクションを1秒に1回実行する必要があります。

今のところ私のアプローチは、より良いアイデアがないため、各スニペットを配列に追加し、eval()でループすることです。これは私のコードです:

var queue = [];

// On player or AI action
queue.push('attack()'); // Could be walk('left'), jump() etc.

// On new frame
for(var i=0;i<queue.length;i++){
  eval(queue[i]);
  }
queue = [];

私のアプローチはひどいものだと思いますが、自分が何をしたいのかを明確にしたかったので、このような問題はそれほど珍しいことではないと思います。情報/アイデアはありますか?

4

2 に答える 2

3

それひどいです-eval悪です。代わりに、クロージャを使用してください:

var queue = [];

queue.push(function() { attack(); });

while (queue.length) {
    queue.shift().call();
}

これは一般的なケースですが、この場合は単純化できます。これfunction() { attack(); }は、より複雑で低速な記述方法attackであるため、queue.push(attack)同様に機能します(アクセス可能な場所で定義されている場合function attack() { ... })。call(thisobj, param)明らかに、関数がパラメーターを受け取る場合(つまり、各関数が異なるパラメーターを受け取る場合、呼び出しで統一されたパラメーターリストを指定できます)、それを行うことはできません。

追加のクエリを編集します。

あなたが書いたコードでは、これは変数をクロージャーに取り込むはずです。変数を変更すると、その値が実行時に取得される値になります。あなたが得たならundefined、私はあなたがcloserEnemy = undefined後でどこかで実行したと思います。これは、たとえば、クリックハンドラーをループ内の複数の要素にバインドし、ハンドラーでループカウンターを使用しようとした場合のエラーの一般的な原因です。ハンドラーは、その値ではなくカウンターをキャプチャし、後で常に評価します。要素の数(ループが終了したときに残された最後の値)。

変数ではなく値をキャプチャするには、次のトリックを使用します。

(function(capturedCloserEnemy) {
  queue.push(function() {
    attack(capturedCloserEnemy);
  });
})(closerEnemy);

(変数は読みやすさのために異なる名前が付けられています。それらはすべて同じ名前にすることができ、シャドウイングのため、問題にはなりません。)

于 2012-12-20T05:54:43.837 に答える
1

あなたのアプローチの問題はそれです:

  1. evalを使用しています

    evalを使用する際のリスクについてはすでに聞いたことがあります。そうでない場合は、 MDNからこのドキュメントを確認してください。

  2. ループを使用しています

    ループを使用する場合、JavaScriptはできるだけ早くループを終了しようとします。これにより、UIがブロックされます。これは、この方法でループを開始すると、アニメーションが最初のアニメーションでのみ移動し、フリーズし、キューの最後のアニメーションで終了するように見えることも意味します。

両方の問題の解決策として、実行しようとしている関数への参照をキューにプッシュしてみませんか。また、UIのブロックを防ぐために、代わりにタイマーを使用してください。

var queue = [];

//actions as functions
function attack(params){...}
function block(params){...}
function walk(params){...}

//our animation timer
var animationTimer = setInterval(function(){
    //remove the action from the queue and execute
    var nextAction = queue.shift();
    //if we shifted something, execute
    if(nextAction){
        nextAction.call();
    }
},1000);

//to insert into the queue, push the reference of the function instead.
queue.push(attack);
于 2012-12-20T06:00:12.580 に答える