Soll ich Events in einem XNA-Spiel verwenden?

8

Ich habe eine Schaltflächenklasse erstellt, die eine Schaltfläche auf dem Bildschirm zeichnet. Wenn ich darauf klicke, möchte ich sehen, dass etwas passiert. In WinForm würde ich einfach das Ereignis OnClick der Schaltfläche verwenden. Was ist mit XNA?

Sollte ich meiner Schaltflächenklasse ein OnClick-Ereignis hinzufügen? Ist das eine gute Praxis? Wie gehen Sie ansonsten mit Ereignissen in Ihrer Spielschleife um?

Martin
quelle
Sie müssen Ihr eigenes onClick-Ereignis schreiben. Etwas, das die aktuelle Mausposition einnimmt und diese mit der Position Ihrer Schaltfläche vergleicht
Jeff

Antworten:

7

Der einzige Grund gegen die Verwendung eventin einem Spiel besteht darin, dass beim Erstellen eines Delegaten zum Anhängen an den Ereignishandler ein Heap-Objekt erstellt wird, das eine Speicherbereinigung verursachen kann, die auf Xbox 360 (und möglicherweise WP7) zu einem Schluckauf mit Bildrate führen kann es).

Im Allgemeinen sollte dies für eine Spiel-Benutzeroberfläche, die Sie einmal eingerichtet und einfach laufen lassen, nicht relevant sein.

Das Aufrufen eines Ereignishandlers ist bei einigen anderen verfügbaren Methoden ein winziges, winziges bisschen langsamer. Und das ist auch für eine Benutzeroberfläche absolut irrelevant. (Es kommt nur für die mikrooptimierte Zahlenkalkulation ins Spiel).

Solange Sie also nicht ohne weiteres herumlaufen, um Event-Handler zuzuweisen, unterscheidet sich die Wahl der Verwendung eines eventin einem Spiel nicht von der Wahl der Verwendung eines in einer regulären Anwendung.

Das Kopieren des Designs von WinForms für die Benutzeroberfläche Ihres Spiels ist vollkommen in Ordnung.

(Es ist erwähnenswert, dass eine Einschränkung von Ereignissen darin besteht, dass es sich um "versteckte" starke Referenzen handelt, die Objekte unbeabsichtigt am Leben erhalten können, wenn Sie den Handler nicht entfernen. Dies ist sowohl für Spiele als auch für reguläre Anwendungen relevant.)

Andrew Russell
quelle
4

Es ist durchaus akzeptabel, Ereignisse zu verwenden, um Dinge wie Klicks und andere Interaktionen mit Ihrer Schaltflächenoberfläche zu verarbeiten. Es ist sicherlich eine überlegene Methode als die, bei der der ButtonTyp in Unterklassen unterteilt wird , um benutzerdefiniertes Verhalten zu implementieren.

Eine andere ungewöhnliche Alternative ist das Anhängen von Skripten an Schaltflächen und andere Elemente der Benutzeroberfläche. Dies ist jedoch aufwändiger (es sei denn, Sie verfügen bereits über ein robustes Skriptsystem) und ohnehin nicht unbedingt besser.

Möglicherweise möchten Sie auch das Konzept der " Sofortmodus-GUIs " untersuchen, die eine andere Möglichkeit zur Verarbeitung von Eingaben bieten.


quelle
Ich frage mich nur, wie sich Ihre Antwort von meiner unterscheidet. Gibt es eine Methode, die sich zwischen uns unterscheidet?
Ali1S232
3

Es gibt drei gängige Ansätze, die ich in Spiel-Engines gesehen habe. Ich bin mir nicht sicher, ob XNA alle drei unterstützt, aber hier sind sie:

  1. Sie können eine Klasse von Ihrer Schaltflächenklasse erben und OnClickFunction in Ihrer CustomButton-Klasse überschreiben. Der Vorteil ist, dass Sie nicht überprüfen müssen, ob die Schaltfläche gedrückt wurde, sondern Sie bei jedem Klicken darüber informiert werden. Dies kann jedoch zu einer Überbeanspruchung der Vererbung führen.

  2. Sie können eine Funktion OnClick definieren und an die Butten-Klasse OnClickEvent übergeben (genau wie bei der normalen Behandlung von c # -Ereignissen). Dies hat den gleichen Vorteil wie das vorherige und Sie müssen sich keine Sorgen über eine Überbeanspruchung der Vererbung machen.

  3. Sie müssen in Ihrer Hauptschleife überprüfen, ob auf diese Schaltfläche geklickt wird oder nicht. Bei dieser Methode ist es kein wirkliches Ereignis. Der Nachteil ist also, dass Sie sich selbst überprüfen müssen, wann immer Sie etwas basierend auf Tasteneingaben tun müssen, aber es hat den Vorteil, dass Sie steuern können, wo die Tasten wirklich überprüft werden und wirksam werden.

Ali1S232
quelle
2

Ich habe die Verwendung von .net-Ereignissen eingestellt und alle meine Ereignisse und Änderungen im Puffer gespeichert:

public sealed class GameStateData
{
    public bool IsEmpty = true;
    public List<EventData> EventDatas = new List<EventData>();
    public List<ChangeData> ChangeDatas = new List<ChangeData>();
    ...//your additional data

    public void Reset()
    {
        IsEmpty = true;
        ManifoldDatas.Count = 0;
        ChangeDatas.Count = 0;
    }
}

public struct ChangeData
{
    public Node Sender;
    public short PropertyIndex; // predefined property index (f.e. (short)MyIndexEnum.Life)
    public object OldValue;
    public object NewValue;
    public object AdditionalData;
}

Vorteile:

  1. Für die Multithreading-Unterstützung müssen Sie lediglich die Puffer austauschen und alle Ereignisse und Änderungen im Render-Thread verarbeiten.
  2. Jede Änderung des Spielschritts wird gespeichert, sodass jede Spiellogik auf einer Kombination von Ereignissen basieren kann. Sie können sogar eine Zeitumkehr implementieren.
  3. Sie müssen keine Ereignisfelder erstellen, die die Größe eines einzelnen Objekts erhöhen. Für die Spielelogik ist in den meisten Fällen nur ein einziger seltener Abonnent erforderlich.
  4. Es gibt fast keine zusätzliche Speicherzuweisung (ausgenommen Boxing Cases) (WP7, XBox und andere kritische Micro Frameworks).
  5. Sie können verschiedene Ereignissätze verwenden, die vordefinierte GameStateData für Objekte verarbeiten.

Nachteile:

  1. Mehr Speicherplatz, obwohl Sie nur 3 Puffer benötigen (Spiel, Tausch und Rendern).
  2. Schreiben von zusätzlichem Code zu Beginn, um die erforderliche Funktionalität zu implementieren.

Übrigens benutze ich manchmal beides: Ereignismodell und Puffermodell.

Romanenkov Andrey
quelle