Verzögerung beim Start eines Tastendrucks entfernen

11

Ich mache ein einfaches Spiel und eines der Probleme, auf die ich gestoßen bin, ist die nervige Verzögerung beim kontinuierlichen Drücken einer Taste.

Wenn ich zum Beispiel (für eine sehr lange Zeit) drücke Up, bewegt sich mein Objekt um 1 Einheit nach oben, nicht nach oben (für ca. 1 Sekunde) und bewegt sich dann kontinuierlich um 1 Einheit nach oben (ohne Verzögerungen).

Derzeit verwende ich dies, um das Objekt (SDL2) zu verschieben:

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
    }
}

Was ich haben möchte, ist, die Verzögerung zu entfernen, damit sich das Objekt sofort Upsehr schnell bewegen kann. Gibt es eine Möglichkeit, dies zu tun?

Rakete1111
quelle

Antworten:

19

Wenn Sie darauf warten, dass Key-Down-Ereignisse ausgelöst werden, sind Sie wahrscheinlich der Wiederholungsrate des Key-Ereignisses ausgeliefert, die das Betriebssystem steuert (und die Benutzer selbst angeben können).

Stattdessen möchten Sie möglicherweise SDL_GetKeyboardStateoben in Ihrer Spielaktualisierungsschleife (dem Teil des Updates, der in jedem Frame stattfindet, unabhängig davon, ob ein Ereignis eingetreten ist oder nicht) aufrufen , um den Status der Tastatur abzurufen und zu überprüfen, ob der Status aktiviert ist Die Taste ist während eines einzelnen Frames gedrückt oder nicht.


quelle
Wäre es nicht besser, Fensternachrichten abzuhören? Beim Abrufen verpasse ich manchmal sehr kurze Tastendrücke und dieses Problem wird schlimmer, wenn die Framerate niedrig ist.
Roy T.
@ RoyT. Es hängt wirklich von Ihrem Spiel und der Art der Aktion ab, die Sie mit der Taste auslösen möchten. Wenn der Tastendruck einmalig ist, wie eine "Aktionstaste", die einen Dialog schließt, ist eine Nachrichtenwarteschlange der richtige Ansatz - Sie möchten auf ein atomares Ereignis warten. - Wenn andererseits der Schlüsselstatus einen fortlaufenden Zustand wie eine "Verschiebungs" -Taste darstellt, ist die Logik normalerweise while key UP is down move 30 units per second- und pro Sekunde nur dann sinnvoll, wenn Sie eine messbare Zeit zwischen Taste runter und rauf haben - normalerweise mehr als ein Bild.
Falco
@ RoyT. Sie können auch Nachrichten abhören (und damit Ihr eigenes Tastaturstatus-Array aktualisieren). Ich habe mich entschieden, diesen Ansatz wegen seiner Einfachheit vorzuschlagen. Sie können aber sicherlich eine andere Antwort schreiben. Der wichtige Teil besteht nur darin, sich nicht auf Betriebssystemnachrichten zu verlassen, um zu überprüfen, ob der Schlüssel ständig gedrückt ist , da Sie dadurch an die Wiederholungsrate des Betriebssystemschlüssels gebunden werden.
Und mit Frame meinst du Game Tick, nicht Video Frame, oder? Weil wir keine Plebs sind und die Spielelogik in der Render-Schleife codieren. :-)
corsiKa
@JoshPetrie Ich stimme vollkommen zu, wollte nur auf diese kleine Einschränkung hinweisen, wenn Sie ein "Klicken" anstelle eines "Drücken" überprüfen müssen. :)
Roy T.
10

Eine alternative Möglichkeit (Joshs Ansatz ist auch großartig!) Besteht darin, einen Booleschen Wert einzurichten SDL_KEYDOWNund möglicherweise auch alle wiederholten Schlüsselereignisse zu ignorieren. Dies können Sie tun, indem Sie das repeatMitglied des Schlüsselereignisses überprüfen .

Dann könnten Sie Ihren eigenen Timer implementieren, der nichts Besonderes sein muss, und die Tastenwiederholung selbst implementieren. Sie können die Aktion entweder direkt vom Timer aus auslösen oder sogar ein SDL_KEYDOWNEreignis generieren und die Lösungen vereinheitlichen.

Tyyppi_77
quelle