10

update()ユーザーからのキーボード入力を「更新」するメソッドを1秒間にn回実行しているので、後でプログラムのロジック部分で読み取ることができます。そのため、SDLドキュメントでこれを実装する2つの方法を見つけましたが、どちらを使用すればよいかわかりません。

1; SDL_PollEventを使用してすべてのイベントをループし、キーのダウン/アップイベントを検索し、キーの状態をマップに保存して、プログラムのロジックで各キーの状態を確認できるようにします。

注:または、SDL_PollEventの代わりにSDL_PeepEventsを使用して、重要なイベントタイプのみを取得することもできます。したがって、キュー上のイベントを「破棄」することはありません。

std::map<int, bool> keyboard; // Saves the state(true=pressed; false=released) of each SDL_Key.

void update()
{
    SDL_Event event;
    while( SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
            keyboard[event.key.keysym.sym] = false;
            break;
        case SDL_KEYUP:
            keyboard[event.key.keysym.sym] = true;
            break;
        }
    }
}

2; フレームごとにキーボードからスナップショットを取り、簡単に読み取れるようにします。

Uint8* keyboard;

void update()
{
    SDL_PumpEvents();
    keyboard = SDL_GetKeyState(NULL);
}

上記の実装のいずれかで、私は次のように読むことができますkeyboard

if (key_map[SDLK_Return]) printf("Return has been pressed.");

また、そうする別の方法はありますか?

4

3 に答える 3

10

私は、現在の状態だけでなく、どのキーがダウンしたか、どのキーがアップしたかを示す、3 つの配列を埋める 1 のバリエーションを実行することを好みます。これにより、コード内でこれらのイベントを (以前のスナップショットと比較せずに) 簡単に確認できますが、最も重要なのは、1 フレーム未満のイベントを見逃さないことです。たとえば、マシンが遅いためにゲームが 10 fps で実行されている場合、更新ルーチンの 2 つの呼び出しの間にユーザーが重要なキーを押して放すと、システムはそれを登録しません。これは非常にイライラします。

SDL は、キーが押されたときにもキー イベントを送信します。これにより、各キー アップに対して複数のキー ダウン イベントを持つことができます。これは、キーボード制御のメニューなど、項目のリストをキーボードでスクロールする機能を実装する場合に特に便利です。

于 2012-07-28T19:39:09.780 に答える
5

解決策 2 を使用する必要があります。

なんで?SDL_GetKeyState()ドキュメントが指摘しているように、それを使用する前に、状態配列を更新するために呼び出す必要がありますSDL_PumpEvents()

を呼び出すとSDL_PollEvent()、暗黙的に が呼び出されますSDL_PumpEvents()SDL_GetKeyState()したがって、基本的にはとにかく配列を更新します。これらのイベントを手動で解析することにより、SDL が既に収集したものと同じ情報を保持する 2 番目の配列 (実際にははるかに遅いマップ) を作成するだけです。

したがって、最初の解決策は、同じことを2回行うことを意味するとあえて言います。また、キーストロークの繰り返し ( SDL_EnableKeyRepeat() )などをサポートすることにした場合は、SDL の大部分を再実装することになります。

于 2012-07-28T08:24:04.587 に答える
4

この質問はかなり古いと思いますが、私の答えは誰かに役立つ可能性があります。個人的に、私は で 2 つの配列を使用しSDL_GetKeyStateます。現在のフレームのキーボード状態を保持する 1 つの配列と、その最後のフレームのキーボード状態を保持する 1 つの配列を格納します。(一部のmemcpyコマンドを使用すると、それらを簡単に更新できます。) これらの 2 つの配列と共に、"A" のような文字列を SDL スキャンコード値に変換するマップがありますが、これはオプションです。

次に、何かが離されたか押されたかを確認する必要がある場合は、2 つの配列を組み合わせて確認できます。(私はこれを関数にしました。) たとえば、キーがこのフレームで押されたが、前のフレームで押されていないことがわかっている場合、明らかにこのフレームで押されただけです。if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}

次に、リリースされたものに対して反対のことを行います。この方法は、実装と使用が非常に簡単だと思います。

于 2016-02-27T01:48:50.467 に答える