Datengesteuerte Animationszustände

14

EDIT: Um genau zu klären, was meine Frage ist: Ist dies eine gute Möglichkeit, Animationen / Animationsstatus in einer Game-Engine mit Blick auf die Erstellung / Verwaltung von Inhalten zu behandeln? Was sind die Fehler bei dieser Vorgehensweise und was wäre eine alternative Vorgehensweise? - Obwohl meine Antwort teilweise in den Kommentaren beantwortet wurde, scheint es der richtige Weg zu sein.

Ich versuche, Animationen in einem 2D-Game-Engine- Hobbyprojekt zu verarbeiten, ohne sie hart zu codieren. Hartcodierte Animationszustände scheinen mir ein weit verbreitetes, aber sehr merkwürdiges Phänomen zu sein.

Ein kleiner Hintergrund: Ich arbeite mit einem Entitätssystem, in dem Komponenten eine Menge Daten sind und Subsysteme auf sie einwirken. Ich habe mich für ein Abfragesystem entschieden, um den Animationsstatus zu aktualisieren.

Mit Animationszuständen meine ich: "walking_left", "running_left", "walking_right", "shooting", ...

Meine Idee, mit Animationen umzugehen, bestand darin, sie als datengetriebenes Modell zu entwerfen . Daten könnten in einer XML-Datei, einem RDBMS, ... gespeichert und zu Beginn eines Spiels / Levels / ... geladen werden. Auf diese Weise können Sie Animationen und Übergänge auf einfache Weise bearbeiten, ohne den Code überall in Ihrem Browser ändern zu müssen Spiel.

Als Beispiel habe ich einen XML-Entwurf der Datendefinitionen angefertigt, die ich mir vorgestellt hatte.

Ein sehr wichtiges Datenelement wäre einfach die Beschreibung einer Animation . Eine Animation hätte eine eindeutige ID (einen beschreibenden Namen). Es würde eine Referenz-ID für ein Bild enthalten (das von ihm verwendete Sprite-Sheet, da unterschiedliche Animationen möglicherweise unterschiedliche Sprite-Sheets verwenden). Die Bilder pro Sekunde, mit denen die Animation ausgeführt werden soll. Die "Wiedergabe" hier definiert, ob eine Animation einmalig oder unendlich ausgeführt werden soll. Dann habe ich eine Liste von Rechtecken als Rahmen definiert.

<animation id='WIZARD_WALK_LEFT'>
    <image id='WIZARD_WALKING' />
    <fps>50</fps>
    <replay>true</replay>
    <frames>
        <rectangle>
            <x>0</x>
            <y>0</y>
            <width>45</width>
            <height>45</height>
        </rectangle>
        <rectangle>
            <x>45</x>
            <y>0</y>
            <width>45</width>
            <height>45</height>
        </rectangle>
    </frames>
</animation>

Animationsdaten würden in einem geladen und gehalten werden Animation Ressourcenpool und referenziert von Spiel Entitäten , die es verwenden. Es würde als eine Ressource wie ein Bild, ein Ton, eine Textur behandelt werden, ...

Das zweite zu definierende Datenelement wäre eine Zustandsmaschine, mit der Animationszustände und -übergänge verarbeitet werden können. Dies definiert, in welchem ​​Zustand sich eine Spieleinheit befinden kann, in welche Zustände sie übergehen kann und was diese Zustandsänderung auslöst.

Diese Zustandsmaschine würde sich von Entität zu Entität unterscheiden. Weil ein Vogel die Zustände "Gehen" und "Fliegen" haben könnte, während ein Mensch nur den Zustand "Gehen" haben würde. Es könnte jedoch von verschiedenen Entitäten geteilt werden, da wahrscheinlich mehrere Menschen den gleichen Status haben (insbesondere wenn Sie einige gemeinsame NPCs wie Monster usw. definieren). Zusätzlich kann ein Ork die gleichen Zustände haben wie ein Mensch. Nur um zu demonstrieren, dass diese Zustandsdefinition nur von einer ausgewählten Gruppe von Spieleinheiten geteilt werden kann .

<state id='IDLE'>
  <event trigger='LEFT_DOWN' goto='MOVING_LEFT' />
  <event trigger='RIGHT_DOWN' goto='MOVING_RIGHT' />
</state>
<state id='MOVING_LEFT'>
  <event trigger='LEFT_UP' goto='IDLE' />
  <event trigger='RIGHT_DOWN' goto='MOVING_RIGHT' />
</state>
<state id='MOVING_RIGHT'>
  <event trigger='RIGHT_UP' goto='IDLE' />
  <event trigger='LEFT_DOWN' goto='MOVING_LEFT' />
</state>

Diese Zustände können von einem Abfragesystem verarbeitet werden . Jedes Spiel-Häkchen erfasst den aktuellen Status einer Spieleinheit und überprüft alle Auslöser. Wenn eine Bedingung erfüllt ist, wird der Status der Entität in den Status "goto" geändert.

Der letzte Teil, mit dem ich zu kämpfen hatte, war das Binden von Animationsdaten und Animationszuständen an eine Entität . Der logischste Ansatz schien mir, einen Zeiger auf die von einer Entität verwendeten Zustandsmaschinendaten einzufügen und für jeden Zustand in dieser Maschine zu definieren, welche Animation sie verwendet.

Hier ist ein XML-Beispiel, wie ich das Animationsverhalten und die grafische Darstellung einiger gebräuchlicher Entitäten in einem Spiel definieren würde, indem ich den Animationsstatus und die Animationsdaten-ID anspreche. Beachten Sie, dass sowohl "Wizard" als auch "Orc" den gleichen Animationsstatus haben, jedoch eine andere Animation. Eine andere Animation kann auch ein anderes Sprite Sheet oder sogar eine andere Sequenz von Animationen bedeuten (eine Animation kann länger oder kürzer sein).

<entity name="wizard">
    <state id="IDLE" animation="WIZARD_IDLE" />
    <state id="MOVING_LEFT" animation="WIZARD_WALK_LEFT" />
</entity>

<entity name="orc">
    <state id="IDLE" animation="ORC_IDLE" />
    <state id="MOVING_LEFT" animation="ORC_WALK_LEFT" />
</entity>

Beim Erstellen der Entität wird eine Liste von Status mit Statusmaschinendaten und einer Animationsdatenreferenz hinzugefügt.

In Zukunft würde ich das Entitätssystem verwenden, um ganze Entitäten zu erstellen, indem ich Komponenten in einem ähnlichen XML-Format definiere.

-

Dies ist, was ich nach einigen Nachforschungen gefunden habe. Allerdings hatte ich einige Probleme damit, es in den Kopf zu bekommen, also hoffte ich auf ein Feedback. Gibt es hier etwas, was keinen Sinn ergibt, oder gibt es eine bessere Möglichkeit, mit diesen Dingen umzugehen? Ich habe die Idee verstanden, durch Frames zu iterieren, aber ich habe Probleme, einen Schritt weiterzugehen, und dies ist mein Versuch, dies zu tun.

user8363
quelle
1
Ich habe mir eine ähnliche Idee zum Speichern von Animationsdaten ausgedacht, obwohl ich die Auslöser nicht berücksichtigt habe. Hier ist ein kurzer Artikel, den ich darüber geschrieben habe, und ein Link zu einem von mir geschriebenen XNA-Projekt , das die XML-Datei verwendet und die Animationsseite der Dinge behandelt. Ich habe ein paar Dinge, die anders sind, wie das Konzept der Mengen und Sequenzen, aber ansonsten denke ich, dass Sie auf dem richtigen Weg sind.
John McDonald
2
Nicht, dass Ihr Design schlecht ist (es ist nicht so, wie in früheren Zeiten), aber was genau ist Ihre Frage hier? Ich denke, es könnte wirklich klarer sein.
MrCranky
@ John - Danke Kumpel, ich werde es mir später am Abend ansehen. @ MrCranky - Na ja, meistens genau das, was du gesagt hast. Wenn es irgendwelche guten und möglicherweise Tipps / Links zu etablierteren Methoden gibt. Ich bin hier wirklich im Dunkeln, was Erfahrung angeht.
User8363
1
Ich würde dem gerne eine positive Note für die Tiefe der bereitgestellten Informationen geben, aber, um MrCranky zu wiederholen, verfolge ich die Frage nicht wirklich. Für meinen persönlichen Rat (der sich aus dem Aufbau eines solchen Systems vor ein paar Wochen ergibt) würde ich sagen, dass Sie genau richtig sind.
Mike Cluck
@ MikeC Das ist genau die Antwort, die ich brauchte. Ich entschuldige mich dafür, dass ich meine Frage nicht klarer beantworten konnte. Vielleicht würde es eher wie eine Frage aussehen, wenn ich nicht auf den Punkt gekommen wäre :). Tatsache ist, dass ich nicht viele Ressourcen finden konnte, die sich mit Animationszuständen befassten und die es hartcodiert haben, so dass das Erstellen / Ändern von Inhalten ein Albtraum wäre. Meine Frage lautet also: Ist dieser Ansatz richtig oder nicht? Und wenn ihr es sagt, dann ist das in Ordnung :).
User8363

Antworten:

4

Animationsclips lassen sich am besten in einfachen alten Daten beschreiben, wie Sie es in Ihrem ersten XML-Snippet getan haben. Sie können dies von Hand machen oder aus einem Kunstpaket exportieren. In beiden Fällen möchten Sie wahrscheinlich eine Pipeline erstellen, die sie aus einem für Menschen lesbaren Zwischenformat wie XML in eine nette und schnell zu ladende Form bringt.

Der nächste Schritt ist, das Ding rendern zu können. Wenn Sie eine Art Szenendiagramm verwenden, bedeutet dies wahrscheinlich, dass Sie einen Animationsknoten dafür erstellen. Sie sollten in der Lage sein, dem Animationsknoten mitzuteilen, welche Animation gerade abgespielt wird und wo sich diese in der Timeline befindet. Stellen Sie sicher, dass Sie die Informationen zum Begrenzungsrahmen auf dieser Ebene verfügbar halten, damit Sie sie problemlos in Ihr Keulungssystem einspeisen können.

Jetzt wollen Sie einer Spieleinheit eine Animation zuordnen. Ich neige dazu, ein komponentenbasiertes Modell zu verwenden, für mich bedeutet dies also und AnimState-Komponente. Dies ist Ihre Zwischenschicht zwischen Gameplay und Rendering. Es verfolgt, welche Animation eine Entität abspielt, welche Spielmodi (Endlosschleifen, einmaliges Abspielen, Ping-Pong usw.) und wann sie ablaufen. Es kann Ereignisse wie "animover" an die Entität zurücksenden und den Status des Animationsknotens bei Bedarf aktualisieren . AnimStates für aktive Entities werden einmal pro Sim-Tick aktualisiert, wenn sie eine Animation abspielen.

Eine animierte Komponente ist wahrscheinlich genug für einfache Spielgegenstände (grundlegende Hintergrund-Requisiten und ähnliches), aber für kompliziertere Objekte möchten Sie eine Zustandsmaschine verwenden, um sie zu verwalten. Dies lässt sich am besten in einer Skriptsprache wie Lua oder Python ausdrücken. Ein Status kann mehrere Funktionsblöcke (onEnter, onExit, onUpdate, onEvent) sowie eine Zeitleiste enthalten, die bestimmte Aktionen und Trigger angibt, die zu bestimmten Zeiten ausgeführt werden sollen. Wahrscheinlich verfügen Sie über eine Art Manager-Klasse, die für die Aktualisierung dieser Zustandsautomaten sowie für das Auslösen der Timeline-Rückrufe bei deren Auftreten verantwortlich ist. Sie sollten versuchen, diese Dinge so ereignisbasiert wie möglich zu halten, da jedes OnUpdate, das Sie schreiben, lineare Kosten mit der Anzahl der Entitäten verursacht. Sie werden auch Tags angeben wollen ('attacking', 'idle', 'ignoreinput', etc), die sowohl mit ganzen Staaten als auch mit bestimmten Zeitregionen von Staaten verbunden sind. Wahrscheinlich möchten Sie auch einige übergeordnete Ereignishandler, die sich auf den gesamten Zustandsgraphen und nicht nur auf einen bestimmten Zustand beziehen.

'Sentient'-Charaktere werden wahrscheinlich auch eine Art KI haben. Ich neige dazu, eine bestimmte "Bewegungskomponente" herzustellen, die das Herumlaufen regelt. Es ist über ein System von Signalen und Ereignissen mit der Strategie verbunden und fragt nach Status-Tags. Es kann angewiesen werden, "mit einer bestimmten Geschwindigkeit in eine bestimmte Richtung zu laufen" oder "in eine bestimmte Richtung zu laufen". Übergeordnete KI-Komponenten (wie ein Verhaltensbaum oder was auch immer) können diese Schnittstelle dann verwenden, ohne sich um die Details zu kümmern.

Kevin
quelle
1

Das beste datengesteuerte Animationssystem, das ich bisher gesehen habe, ist der Blend Tree . Wirklich, es ist verdammt gut und kann alles, wonach Sie hier fragen. Laut AIGameDev.com ist es jetzt der De-facto-Standard in der Branche, und ich glaube, sie haben Recht.

Leider habe ich bei einem schnellen Googeln keine gute Ressource gefunden, aber Sie können dies oder jenes ausprobieren , um sich einen Überblick zu verschaffen. Es gibt auch einen kostenpflichtigen Artikel auf AIGameDev.com. Ich weiß nicht, ob es sich lohnt, einen Premium-Account zu erhalten.

Laurent Couvidou
quelle
Dies ist eine sehr gute Ressource, danke. Ich suche solche Informationen.
User8363
1
Das Mischen von Animationen ist mit diskreten Sprite-Sheets nicht möglich, nur mit kontinuierlicher Skelett-Animation
AlexFoxGill