4

HTML5キャンバスとjavascriptを使用して小さなゲームに取り組んでいます。また、キーボードのキーがときどき「スタック」することを除けば、非常にうまく機能しています。キーダウンイベントは登録されますが、キーアップイベントが登録されない場合があります。これは通常、一度に複数のキーを押すと発生するため、一部はハードウェアまたはOSの障害ですが、これを回避する方法について誰かがアイデアを持っていることを期待しています。私のコードの関連部分(coffeescriptで書かれています):

press = (direction) ->
    switch direction
        when 'W'
            game.keys.W = true
        when 'S'
            game.keys.S = true
        when 'A'
            game.keys.A = true
        when 'D'
            game.keys.D = true


release = (direction) ->
    switch direction
        when 'W'
            game.keys.W = false
        when 'S'
            game.keys.S = false
        when 'A'
            game.keys.A = false
        when 'D'
            game.keys.D = false

doKeyDown = (evt) ->
    switch evt.keyCode
        when 87 then press 'W'
        when 83 then press 'S'
        when 65 then press 'A'
        when 68 then press 'D'

doKeyUp = (evt) ->
    switch evt.keyCode
        when 87 then release 'W'
        when 83 then release 'S'
        when 65 then release 'A'
        when 68 then release 'D'

window.addEventListener('keydown', doKeyDown, false)

window.addEventListener('keyup', doKeyUp, false)

基本的なもの。javascriptが完全にイベント駆動型でなくても問題はありませんが、何ができるでしょうか。問題を回避する方法についての私の現在の考えは、2つまたは3つのキーの容量を持つ、キーを押すためのキューを追加することです。制限を超えると、最初のキーが削除され、「false」に切り替えられます。 。それでも、回避できるはずのときに、このような人為的な制限を追加するのは奇妙に思えます!

したがって、問題は、回避策に頼ることなく、主要な状態を正確に保存するための簡単な方法があるかどうかです。できれば、ゲームのフレームレートとは関係なく機能するものが望ましいです(1000 fpsで実行されていても、3 fpsで実行されていても、同じように機能するはずです)。

4

4 に答える 4

3

keydownイベントは急速に発生するため、最後にキーを聞いたときにキーが押されたことを示すタイムスタンプを保存できます。

when 'A'
    game.keys.A = [true, +newDate()]

次に、インターバル機能を実行して、まだ押されていると登録されているがkeydown、一定期間(たとえば、1秒)イベントを送信していないキーをチェックし、リリース済みとして設定します。

上記の例では、多くのコードをリファクタリングする必要がある場合があります(game.keys.Aブール値ではなく配列になっているため)。代わりに、タイムスタンプを独自のオブジェクトに保持できます。

last_keydown_times = {};
...

when 'A'
    game.keys.A = true
    last_keydown_times['A'] = +new Date();

間隔関数にlast_keydown_times(おそらくfor...inループ内の)のメンバーをチェックさせ、期限切れの値をチェックさせます。

setInterval(function() {
    var now = +new Date();
    for(key in last_keydown_times) {
        if(now - last_keydown_times[key] >= 1000) {
            // run the release code for this key
        }
    }
}, 1000);
于 2012-06-08T15:58:27.163 に答える
2

これがOSXで発生している場合は、キーを押している間はキーアップイベントが発生しないことcmdに注意してください。

AFAICTこの問題の解決策はありません。現在ダウンしているキーを追跡する唯一の方法は、keyup / keydownイベントを使用することです。Macでは、cmdキーを使用するとこの情報が失われます。

于 2013-12-28T21:44:37.703 に答える
1

keydownイベントよりも多くのイベントが実際に予想される動作であることを指摘する価値がkeyupあります。キーを押したままにすると、OSは複数のsとして報告しますkeydown(通常のテキスト入力に文字が挿入されるたびに1つですが、これは発生しますが、デフォルトのキー保持動作を備えたMacOS10.7で)。keyupキーが物理的に解放された場合にのみ、が表示されます。

もちろん、コードはこの問題の影響を受けないはずです。したがって、キーをリリースした後も問題が発生している状況にgame.keys.Aある場合は、問題が発生しているブラウザのバグとして報告する必要があります。回避策はないと思います。可能。trueA

于 2012-06-08T14:57:30.343 に答える
0

これは、より高価なキーボードを除くすべてのキーボードに共通の問題です。

例として、移動する矢印キーと発射するスペースがあるゲームをプレイしてみてください。2つの矢印を押すと、撮影できなくなる可能性があります。

残念ながら、多くのキーボードが異なるため、これを修正するためにできることは何もありません。問題が発生した場合にユーザーがコントロールをカスタマイズできるようにして、この問題のない一連のコントロールに変更できるようにする必要があります。

于 2012-06-08T15:00:14.280 に答える