キーを押し始めたときの遅延を取り除く


11

私は単純なゲームを作成しています。私が遭遇した問題の1つは、キーを押し続けているときの迷惑な遅延です。

つまり、基本的に、たとえば(非常に長い時間)を押すUpと、オブジェクトは1ユニット上に移動し、移動せず(約1秒間)、その後1ユニット上に(遅延なく)連続して移動します。

現在、私はこれを使用してオブジェクト(SDL2)を移動します。

while (SDL_PollEvent(&event))
{
    switch (event.type)
    {
    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_UP:
            //Move object 1 unit up
            break;
        //Other unrelated things omitted
        }
        break;
    //Omitted other cases
    }
}

私が欲しいのは、オブジェクトをすぐUpに素早く移動できるように、遅延を取り除くことです。これを行う方法はありますか?

回答:


19

キーダウンイベントが発生するのを待つことにより、OSが制御するキーイベントの繰り返し率(およびユーザーが自分で指定できる)に翻弄される可能性があります。

代わりに、SDL_GetKeyboardStateゲームの更新ループ(イベントが発生したかどうかに関係なく、すべてのフレームで発生する更新の一部)の上部で呼び出して、キーボードの状態を取得し、アップしているかどうかを確認することができます。個々のフレームでキーが押されているか、押されていません。


ウィンドウメッセージを聞くほうがいいのではないでしょうか?ポーリングを使用すると、非常に短いキーを押し損うことがあります。フレームレートが低いと、この問題はさらに悪化します。
ロイT.

@RoyT。それは本当にあなたのゲームとキーでトリガーしたいアクションの種類に依存します。キーを押すのが1回限りのものである場合、ダイアログを閉じる「アクション」キーのように、メッセージキューが適切なアプローチです。アトミックイベントをリッスンしたい場合です。-一方、キーステータスが「移動」キーのような進行中の状態を表す場合、ロジックは通常while key UP is down move 30 units per second-キーのダウンとアップの間に測定可能な時間がある場合にのみ意味があります-通常、複数のフレーム。
Falco

@RoyT。メッセージを聞くこともできます(そして、それらを使用して独自のキーボード状態配列を更新します)。私はその単純さのためにこのアプローチを提案することを選びました。もちろん、別の答えを書くこともできます。重要なのは、キーが継続的に押されているかどうかを確認するためにOSメッセージに依存しないようにすることです。これが、OSキーの繰り返し率につながるためです。

フレームとは、ビデオフレームではなく、ゲームのティックを意味しますよね?なぜなら、レンダーループではゲームロジックをエンコードしたりエンコードしたりしているわけではないからです。:-)
corsiKa 2016年

@JoshPetrie私は完全に同意します。「プレス」ではなく「クリック」をチェックする必要がある場合は、この小さな警告を指摘したかっただけです。:)
ロイT.

10

別の方法(ジョシュのアプローチも素晴らしいです!)は、にブール値を設定しSDL_KEYDOWN、場合によっては繰り返されるすべてのキーイベントを無視することもできます。repeatキーイベントのメンバーを確認することで実行できます。

次に、特別なことをする必要のない独自のタイマーを実装し、キーの繰り返しを実装することができます。タイマーから直接アクションをトリガーするか、SDL_KEYDOWNイベントを生成して、ソリューションを統合することができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.