Globale Tastaturzustände

7

Ich habe folgende Idee zur Verarbeitung von Tastatureingaben. Wir erfassen Eingaben in der "Hauptspielklasse" wie folgt:

protected override void Update(GameTime gameTime)
{
    this.CurrentKeyboardState = Keyboard.GetState();

    // main :Game class logic here

    base.Update(gameTime);

    this.PreviousKeyboardState = this.CurrentKeyboardState;
}

Verwenden Sie dann die Tastaturzustände (die einen internalGültigkeitsbereich haben) in allen anderen Spielkomponenten wieder. Die Gründe dafür sind 1) Minimierung der Tastaturverarbeitungslast und 2) Verringerung der "Verschmutzung" aller anderen Klassen mit ähnlichen Tastaturstatusvariablen.

Da ich sowohl in der Spiel- als auch in der XNA-Entwicklung ein ziemlicher Neuling bin, würde ich gerne wissen, ob dies alles vernünftig klingt.

UPDATE: Wenn jemand interessiert ist, tatsächliche Utility - Klasse, wie vorgeschlagen David Gouveia , die ich angelegt habe hier gefunden werden kann .

Petr Abdulin
quelle

Antworten:

12

Ja, es ist völlig vernünftig, und ich könnte es dabei belassen!

... aber ich persönlich bevorzuge ein bisschen mehr Kapselung. Anstatt den Status innerhalb der GameKlasse zu verwalten und globalen Zugriff darauf zu gewähren, ziehe ich es vor, ihn stattdessen in eine eigene Klasse zu packen.

Hier ist ein Beispiel aus dem Gedächtnis. Ich bin mir nicht sicher, ob ich ein Detail übersehen habe, aber wichtig ist die allgemeine Idee:

public static class InputManager
{
    public static void Update()
    {
        _previousKeyboardState = _currentKeyboardState;
        _currentKeyboardState = Keyboard.GetState();
    }

    public static bool IsKeyDown(Keys key) 
    {
        return _currentKeyboardState.IsKeyDown(key);
    }

    public static bool IsKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyDown(Keys key)
    {
        return _currentKeyboardState.IsKeyDown(key) && _previousKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key) && _previousKeyboardState.IsKeyDown(key);
    }

    private static KeyboardState _currentKeyboardState;
    private static KeyboardState _previousKeyboardState;
}

Dann Game.Updaterufe ich oben im Manager einfach Update auf:

InputManager.Update();

Und schließlich kann ich überall im Spiel den Wrapper direkt verwenden:

if(InputManager.OnKeyDown(Keys.Space))
{
    // Shoot once
}

Einige Vorteile:

  • Wie in Ihrer Lösung gibt es in der Anwendung nur einen Ort, an dem der aktuelle und der vorherige Tastaturstatus verwaltet werden müssen.
  • Aber anstatt die Spielklasse mit Tastaturverarbeitung zu verschmutzen, ist sie nur dafür in einer eigenen Klasse gekapselt.
  • Die Klasse ist statisch, sodass sie global zugänglich ist. Wenn Sie dies nicht möchten, müssen Sie keinen globalen Zugriff auf Ihre Spielklasse gewähren.
  • Es ist auch leicht wiederverwendbar - wenn Sie ein neues Projekt starten, können Sie diese Klasse einfach vorbeischauen und loslegen.
David Gouveia
quelle
Wenn Sie schon dabei sind, können Sie die API einfach aufzeichnen und wiedergeben. Auf diese Weise können Sie vordefinierte Eingaben später zu Testzwecken verwenden.
Patrick Hughes
@PatrickHughes Könnten Sie bitte etwas auf Ihren Kommentar eingehen? Welche Ansätze kann ich dafür wählen? Einige Links könnten nützlich sein.
Petr Abdulin
2
@PetrAbdulin Sie möchten eine Liste von KeyboardStateObjekten, die Zeitstempeln zugeordnet sind, in einer Struktur behalten . Wenn Sie Ihr Spiel zum Testen spielen, greifen Sie zu gameTime.TotalGameTimejedem Frame und fügen Sie ihn in eine Struktur ein. _currentKeyboardStateSchreiben Sie beim Beenden des Spiels die Liste der KeyboardStates und TimeSpan.Milliseconds ints auf die Festplatte. Wenn Sie das Spiel dann im Test-Eingabemodus ausführen, lesen Sie die KeyboardStates und ints aus dieser Datei und lesen Sie sie aus der Liste, um zu überprüfen, ob der KeyboardStatezugehörige Zeitstempel der nächsten mit der aktuellen gameTime.TotalGameTime.MillisecondsEigenschaft übereinstimmt .
michael.bartnett
@ michael.bartnett vielen dank für die ausführliche erklärung. Das alles macht Sinn.
Petr Abdulin