Skelettanimation und 3D-Modelle: siehe Spine, DragonBones und 3D-Charaktere.

Auf dieser Seite findest du praktische Techniken für Animationen im Visionaire Studio Editor. Die Beispiele beziehen sich vor allem auf Bildsequenzen; einzelne Ansätze lassen sich jedoch auch auf Spine Animationen und 3D Charaktermodelle übertragen.

Hier bekommst du Ideen, wie du Animationen und damit dein ganzes Spiel optimierst, indem du mit weniger Frames trotzdem flüssige Animationen erreichst.

Los geht's.


Was ist der Animationseditor?

Gemeint ist der Animationseditor, den du an vielen Stellen im Editor findest und mit dem du einzelne Frames oder ganze Bildfolgen importierst. Standardmäßig stellst du dort die Dauer aller Frames, die Dauer einzelner Frames, die Abspielreihenfolge und die Zahl der Durchläufe ein. Mit Aktionsteilen, Skripten und geschickt gewählten Frame-Dauern geht aber noch viel mehr.

Vs anim frame sequencer.png


Vorbereitung

Bevor es mit den Tipps losgeht, richtest du ein paar Dinge ein, die einige der Methoden weiter unten brauchen. Das ist ein bisschen Skript, aber nichts Kompliziertes: Lege im Skriptbereich des Editors ein neues Definitionsskript an, nenne es workflow_functions und füge den folgenden Code ein.

math.randomseed( os.time() ) -- init math.random (make sure math.random is actually random each session)
math.random(); math.random(); math.random() -- shake things up a bit & make sure it is actually random

-- * function used to force animation frame range; i.e: frame 2 to 4 or frame 1 to 1, etc. * --
function setAnimFrames(anim, f, t) -- syntax: setAnimFrames(animation name, from, to)
  t = t or f -- fallback in case t equals nil
  if f > t then f = t end -- fallback in case f is greater than t
  ActiveAnimations[anim].FirstFrame = f -- update from animation frame range
  ActiveAnimations[anim].LastFrame =  t -- update to animation frame range
end

Hinweis: Nicht jeder Tipp auf dieser Seite ist eine ausführliche Schritt-für-Schritt-Anleitung. Manche Methoden sind kompliziert und lassen sich kaum so in kleinen Schritten erklären, dass alle sie verstehen; dort gibt es kurze Zusammenfassungen mit Bildern oder Diagrammen. Im Abschnitt Ressourcen findest du aber eine .ved-Projektdatei mit funktionierenden Beispielen für fast alles auf dieser Seite.


Dauer einzelner Frames

Standardmäßig verwenden Animationen die allgemeine Pause (Dauer) aus denAnim propertiesv2.pngEigenschaften der Animation. Aktivierst du dort „Für jedes Bild eine Pause festlegen“, kannst du jedem Frame eine eigene Dauer geben. Das betrifft nur Frames mit einem anderen Wert als -1; Frames mit -1 verwenden weiter die allgemeine Pause.

Damit wirken Animationen lebendiger, etwa als hätten Bewegungen ein gewisses Gewicht. Außerdem sparst du Frames: Soll ein Frame dreimal hintereinander zu sehen sein, musst du dasselbe Bild in anderen Programmen oft dreimal einfügen. In Visionaire stellst du stattdessen einfach die Dauer dieses Frames auf das Dreifache der allgemeinen Pause.


Dynamische Frame-Dauer

Dieser Tipp ist etwas kniffliger, aber sehr wirkungsvoll: Mit einer zufällig erzeugten Dauer zwischen bestimmten Frames werden eintönige, sich wiederholende Animationen natürlicher. Genauso gut baust du damit eine zufällige Pause zwischen zwei Durchläufen ein.

1. Wähle den Frame, der eine zufällige Dauer bekommen soll. Bearbeite ihn überAnim editframev2.pngund öffne das Aktionsfenster überAktionenv2.png.

2. Lege im Aktionsfenster eine neue Aktion an überAddv2.pngund füge einen Aktionsteil „Skript ausführen“ mit etwa folgendem Inhalt hinzu:

Animations["example"].Pause = math.random(1000, 3000) -- set dynamic duration of frame between 1 & 3 seconds

3. Schließe Aktionsfenster und Frame-Editor, wähle den Frame rechts daneben und wiederhole die Schritte. Diesmal setzt du im Aktionsteil „Skript ausführen“ die Pause wieder auf die allgemeine Pause (Dauer) zurück, die du in denAnim propertiesv2.pngEigenschaften der Animation festgelegt hast, etwa so:

Animations["example"].Pause = 40 -- change frame duration back to global pause (duration) value

Das war's. Du kannst diese Methode auf mehrere Frames oder ganze Frame-Bereiche anwenden. Viel Spaß beim Ausprobieren!


Frame-Bereich einer Animation

Mit etwas Skript bringst du die Engine dazu, die Animation nur zwischen bestimmten Frames oder sogar nur auf einem einzigen Frame zu wiederholen. Das ist praktisch für Zustände wie „Tür zu“ und „Tür offen“. Alternativ geht das auch mit mehreren Szenenobjekten, deren Sichtbarkeit du über eine Bedingung oder einen Wert steuerst.


Hinweis 1: Das funktioniert nur bei Animationen in Endlosschleife, denn andere Animationen werden nach ihren Durchläufen ausgeblendet.
Hinweis 2: Wir verwenden die Funktion setAnimFrames() aus der Vorbereitung oben.
Hinweis 3: Die Animation muss bereits laufen.

Einen einzelnen Frame wiederholst du zum Beispiel so:

setAnimFrames("example", 1) -- loop the 1st frame in the animation "example"

Einen bestimmten Frame-Bereich wiederholst du etwa so:

setAnimFrames("example", 2, 4) -- loop between the 2nd & 4th animation frame in the animation "example"

Und so geht es ohne die Funktion setAnimFrames():

-- loop the 1st frame belonging to the animation "example"
ActiveAnimations["example"].FirstFrame = 1
ActiveAnimations["example"].LastFrame = 1


Abspielreihenfolge

Animationen lassen sich vorwärts, rückwärts oder in zufälliger Reihenfolge abspielen. Damit sind auch Pendelanimationen möglich, die erst in die eine und dann in die andere Richtung laufen; dazu mehr im nächsten Abschnitt.

Die Standardreihenfolge legst du in denAnim propertiesv2.pngEigenschaften der Animation fest. Vorwärts spielt die Frames in ihrer Reihenfolge ab, Rückwärts vom letzten bis zum ersten Frame. Zufällig spielt sie durcheinander ab. Das wirkt lebendig und macht zum Beispiel Sprechanimationen abwechslungsreicher, wenn dein Spiel keine Lippensynchronisation hat.

Die Abspielrichtung einer laufenden Animation änderst du zur Laufzeit mit einer Codezeile wie dieser:

ActiveAnimations["example"].PlayOppositeDirection = true -- true = inverse direction; false = default direction


Pendelschleife

Bei einer Pendelschleife läuft eine Animation erst in die eine Richtung und dann zurück.

Dafür gibt es mehrere Wege.

1. Du zeichnest die ganze Bewegung hin und zurück. Das ist für die Optimierung aber schlecht.

2. Du rufst über die Option „Aktion nach Ende der Animation starten“ in denAnim propertiesv2.pngEigenschaften der Animation eine Aktion vom Typ „Von anderer Aktion aufgerufen“ auf.

3. Mit dem Aktionsteil „Animation abspielen“: einmal vorwärts mit Warten, dann rückwärts mit Warten und danach mit dem Aktionsteil „Zu Aktionsteil springen“ zurück zum ersten, falls es eine Schleife werden soll.

4a. Du fügst in den ersten Frame der Animation eine Codezeile wie diese ein:

ActiveAnimations["example"].PlayOppositeDirection = false -- play default direction

4b. Und in den letzten Frame eine Codezeile wie diese:

ActiveAnimations["example"].PlayOppositeDirection = true -- play inverse direction

Hinweis: Diese Methode ist überholt, weil Animationen inzwischen eine eingebaute Pendel-Option haben.


Animation verschieben

Wie bewegst du Animationen über den Bildschirm? Außer die Bewegung direkt in die Animation zu zeichnen, gibt es dafür noch ein paar andere Wege.

Der Aktionsteil „Objekt verschieben“

Es gibt zwei Aktionsteile zum Verschieben von Objekten. „Objekt verschieben“ arbeitet relativ zur Ausgangsposition; wir nehmen hier „Objekt verschieben zu“, das mit festen Koordinaten arbeitet und deshalb einfacher ist.

Die Anwendung ist einfach: Lege einen Aktionsteil „Objekt verschieben zu“ an, verknüpfe ein Objekt, gib das Ziel an und lege fest, wie lange der Weg vom Start zum Ziel dauern soll.


Tweening

Die Tweening-Funktion to() erzeugt einen Übergang vom aktuellen Zustand eines Objekts oder einer Animation zu einem anderen, etwa zu einer neuen Position, Transparenz oder Größe. Sie nimmt mehrere Argumente an und kann alles verändern, was eine Ganz- oder Kommazahl erwartet. Die Syntax:

to(duration, {arguments}, easing, loop, pendulum)

Und so verschiebst du eine Animation von ihrer aktuellen Position an eine neue:

ActiveAnimations["example"]:to(2500, { CurrentPosition = {x = 500, y = 700} }, easeQuintInOut) -- move animation "example" over 2.5 seconds from starting position to 500 by 700 with a slow build up & ending

Hinweis: Die möglichen Easings findest du auf dieser Seite der Lua-Dokumentation.

Kurven

Mit Bézierkurven baust du weiche oder komplexe Bewegungsbahnen, zum Beispiel für einen Vogel, der in die Szene hinabstößt und wieder hinausfliegt, oder für fallende Schneeflocken und Blätter.

Visionaire Studio bietet drei Arten von Kurven:


Kurve

Eine Kurve mit Anfangs- und Endpunkt. Du kannst beliebig viele Knotenpunkte hinzufügen und verschieben, bis die Form passt.

Vs curve.png


Geschlossene Kurve

Eine große Kurve, deren Ende du wieder mit dem ersten Knoten verbindest, sodass eine Schleife entsteht. Viel Spaß mit Unendlichkeitszeichen und Schlangen, die sich selbst in den Schwanz beißen.

Vs curve cont.png


Kurve über Kontrollpunkte

Eine einzelne, besonders weiche Kurve, die du nachträglich über die beiden äußeren Knoten anpasst. Nach dem Anlegen werden alle Knoten bis auf vier ausgeblendet. Im Grunde geht dasselbe auch mit der ersten Variante, diese hier ergibt aber insgesamt weichere Kurven.

Vs curve control.png


Kurven sind eine fortgeschrittene Funktion: Mit Szenenobjekten, Animationen, Interfaces, Partikelsystemen usw. verknüpfst du sie bisher nur per Skript. Kurven in Aktion zeigt die .ved-Datei unten auf dieser Seite. Hier die Syntax:

startCallbackTween(duration, function(x), easing, loop, pendulum)

Und ein Beispielskript:

local n = "curve_example" -- variable containing curve name

-- * move animation along curve over 10 seconds with rotation of parent scene object enabled * --
startCallbackTween(10000, function(x) -- init curve loop function
  local pos = game.CurrentScene.Curves[n]:curveAt(x) -- calculate current curve position
  local direction = game.CurrentScene.Curves[n]:curveDirection(x) -- calculate rotation based on curve position
  game.CurrentScene.Objects["obj_example"].Rotation = direction -- rotates scene object with curve
  ActiveAnimations["anim_example"].CurrentPosition = {x = pos.x, y = pos.y} -- update position of the animation
end, easeLinearIn, true, false)


Rotation

Drehungen sehen am besten aus, wenn das Bild bzw. die Animation flach zum Bildschirm liegt und nicht schräg. Objekte drehst du mit einer Codezeile wie dieser:

-- syntax: to(duration, {arguments}, easing, loop, pendulum)
game.CurrentScene.Objects["example"]:to(5000, {Rotation = math.rad(360)}, easeLinearInOut, true) -- rotate 360º over 5 seconds & loop


Drehung um einen festen Punkt

Das ist etwas anderes als die normale Drehung: Du hältst einen Punkt eines Bilds oder einer Animation fest und verformst und drehst den Rest. Stell dir eine Blume oder einen Baum vor, die sich im Wind wiegen.

Vs pinned rotation.png

Eine eigene Anleitung gibt es dafür hier nicht. Das nötige Skript findest du in der Lua-Dokumentation; binde es als Definitionsskript in dein Projekt ein. Dort gibt es auch Beispiele. Außerdem zeigt die .ved-Datei unten auf dieser Seite diese Funktion und alle anderen Tipps.


Skalierung und Größe

Es gibt mehrere Wege, Animationen und Bilder zur Laufzeit größer oder kleiner zu machen, etwa um Tiefe vorzutäuschen oder einfach zum Vergrößern und Verkleinern.


Objektskalierung

Szenenobjekte (samt ihren Bildern und Animationen) skalierst du mit einer Codezeile wie dieser:

game.CurrentScene.Objects["example"].Scale = 0.5 -- immediately scale object "example" down to 50%

Oder du lässt die Skalierung per Tween vom aktuellen zu einem neuen Wert laufen:

game.CurrentScene.Objects["example"]:to(250, {Scale = 0.5}) -- scale object "example" down to 50% over 250ms

Animationsgröße

Animationen skalierst du mit einer Codezeile wie dieser:

ActiveAnimations["example"].Size = 50 -- immediately scale animation "example" down to 50%

Oder du lässt die Größe per Tween vom aktuellen zu einem neuen Wert laufen:

ActiveAnimations["example"]:to(250, {Size = 50}) -- scale animation "example" down to 50% over 250ms


ScaleXYZ

Eigentlich nur X und Y, das Z ist nur der Vollständigkeit halber. Mit scaleX und scaleY spiegelst du jedes Bild und jede Animation eines Szenenobjekts oder Buttons.

ScaleXY.png

So spiegelst du Bild oder Animation eines Szenenobjekts waagerecht:

game.CurrentScene.Objects["example"].ScaleX = -1 -- default = 1

Und so senkrecht:

game.CurrentScene.Objects["example"].ScaleY = -1 -- default = 1


Zum Schluss

Das sind nicht alle Möglichkeiten; es gibt zum Beispiel noch Aktionsteil-Plugins, Komponenten oder Verhaltensweisen aus dem visuellen Skripting. Hast du weitere Tipps, teile sie gern auf unserem Discord-Server.


Ressourcen

Name Beschreibung
animation_tnt_v2.zip Eine funktionierende .ved-Datei samt Ressourcen. Hinweise stehen in der readme.txt. Visionaire Studio 5.1.9.1 oder neuer erforderlich.