1

player.fireスペースバーが にある場合にtrueになるブール値です。すべてが正常に機能します。 keydown

私が抱えている問題は、配列asteroids.firing.push間隔を制御することです。現在、スペースバーを軽くタップしても、いくつかのインスタンスが追加されます。を使用しています。requestAnimationFrame

push間隔を制御するにはどうすればよいですか?

    if(player.fire){
        var angle = thisShip.rot, 
        hyp = 10; //speed

        var vX = Math.cos(angle) * hyp, 
        vY = Math.sin(angle) * hyp;

        asteroids.firing.push(new asteroids.model.fire(thisShip.x, thisShip.y, vX, vY));
    }

私はこのようなことを試しましたが、間隔を遅くするのpushではなく、パルス効果を作成し、発射シーケンスを何度も再生成します。

    ...
    if(player.fire){
            fireInterval(thisShip);
    }

    function fireInterval(thisShip){
        var angle = thisShip.rot, 
            hyp = 10; //speed

        var vX = Math.cos(angle) * hyp, 
        vY = Math.sin(angle) * hyp;

        asteroids.firing.push(new asteroids.model.fire(thisShip.x, thisShip.y, vX, vY));

        setTimeout(function(){
            fireInterval(thisShip);
        }, 500);
    } 
4

3 に答える 3

5

何が起こっているかというと、更新ごとにこの関数を呼び出しているということです。あなたのエンジンがどのようなものかはわかりませんが、 を使用している場合は最大 60 fps である可能性がありrequestAnimationFrame、できるだけ速くループし、更新が描画に関連付けられていない場合はそれ以上になる可能性があります。

あなたがする必要があるのは、船の銃にある種の状態を置くことです。それが何であるかは問題ではありません...

thisShip.cooldownTime = 250; //ms
thisShip.lastFired =    oldTimestamp;

if (currentTime - thisShip.lastFired >= thisShip.cooldownTime) {
    thisShip.fire(); // push the model, set lastFired to current time, etc...
}

また、他の人が提案していることに関して:

キーボードイベントのリッスンをどのように実装したかはわかりません...
しかし、JSでキーを処理する場合、私が最もやりたいことは、キーボードが必要なだけ多くkeydownkeyupイベントを発生させることです。それをバッファリングする代わりに、キーイベント関数が行う唯一Keyboardのことは、キーが押されているか、押されているかをオブジェクトに伝えることです。

Keyboard更新中にそのオブジェクトをポーリングします。

document.addEventListener("keydown", function (e) {
    var key = e.keyCode;
    if (!!Keyboard[key]) { return; } 
    Keyboard[key] = e.timeStamp;
});


document.addEventListener("keyup", function (e) {
    var key = e.keyCode;
    delete Keyboard[key];
});

キーがダウンしているかどうかを確認するためにポーリングします。キーの値を に設定することで、いつキーを押しe.timeStamp始めたのかがわかるため、船が発砲する頻度を制御できます。

より良いのは、次のようないくつかの抽象化されたシステムをセットアップできることです。

var Keymap = { SPACE : 32, A : 65, ... };
Player1.controls = { FIRE : "SPACE" };

var code = Keymap[Player1.controls.FIRE],
    pressedSince = Keyboard[code]; // timestamp || undefined

これで、クールダウン期間とゲートと比較できるものができました。どれだけ速くタップしても問題ありません。または、デフォルトでキーボードがターボファイアを介して動作する場合、ターボファイアを防ぎ、ホールドダウンオートファイアを許可するために必要なすべてのデータポイントが必要です (250ms でゲートされ、または、画面上に弾丸が 3 つだけになるようにゲートするなど)、キーがタップされ続けていることを検出した場合は、小さい値にゲートして、ボタン マッシャーがボタン ホルダーよりわずかに有利になるようにします。

于 2012-09-16T09:37:11.827 に答える
1

if(player.fire){...}ゲームループ内にコードの一部があると思いますか? もしそうなら、それが頻繁にトリガーされている理由です。これに対する最も一般的な解決策は、ユーザーが再び発砲できるようになる前に、1 つの発火イベントが発生した後に「冷却」期間を設けることです。例えば:

if ( player.fireWait > 0 ) {
  player.fireWait--;
}

if( player.fire && (player.fireWait == 0) ){
  player.fireWait = 20;
  fire( thisShip );
}

上記の 1 つの問題は、ユーザーが発射ボタンを繰り返し押すと、(.fireWaitカウンターが再び 0 に達するまで) 再発射できないことです。これが、onkeydown がどこにあっても、これを行う必要がある理由です。

player.fireWait = 0;

ただし、別の投稿者は、発射メカニズムがほとんどのゲームと同じように機能するためには、キーボード バッファーも使用する必要があると正しく述べています。バッファがないと、ユーザーがスペースを押し続けると、単発のショットが得られます...そして、しばらくすると、突然、急速なショットが得られます。この理由はkeydown、通常のキーボード入力に関連付けられているためです。キーを押したままにすると、何が起こるかがわかりますsssssssssssssssssss.

于 2012-09-16T09:39:04.570 に答える
0

ある種のキーボード バッファを使用する必要があります。このブログ投稿
を見ることをお勧めします。 コメントも非常に役に立ちます。そこから次のサイトを見つけることができます。

あなたが今行っていることは、発射アクションを0.5秒遅らせることだけですが、キャッチされたすべての「キーダウン」はまだ送信されています.
「キーアップ」の使用も検討します。よりうまくいくかもしれません。

于 2012-09-16T09:33:27.113 に答える