{"id":621,"date":"2025-06-11T09:00:00","date_gmt":"2025-06-11T07:00:00","guid":{"rendered":"https:\/\/staratnight.de\/blog\/?p=621"},"modified":"2025-06-07T13:07:40","modified_gmt":"2025-06-07T11:07:40","slug":"animationen-steuern","status":"publish","type":"post","link":"https:\/\/staratnight.de\/blog\/animationen-steuern\/","title":{"rendered":"Animationen steuern"},"content":{"rendered":"\n<p>Nachdem unsere M\u00fcnzen nun schick animiert sind, ist der n\u00e4chste logische Schritt, auch unseren Player zu animieren. Dadurch wird das Spielgeschehen noch dynamischer und die Aktionen unseres Charakters werden klarer visualisiert \u2013 z.B. eine &#8222;idle&#8220;-Animation, wenn er stillsteht, und eine &#8222;walk&#8220;-Animation, wenn er sich bewegt.<\/p>\n\n\n\n<p>Dabei nutzen wir im Grunde dieselben <strong><code>AnimatedSprite2D<\/code><\/strong>&#8211; und <strong>SpriteFrames<\/strong>&#8211;<a href=\"https:\/\/staratnight.de\/blog\/animationen-mit-animatedsprite2d\/\" data-type=\"post\" data-id=\"569\">Konzepte wie bei der M\u00fcnze<\/a>, aber wir steuern die abgespielte Animation jetzt per Skript.<\/p>\n\n\n\n<p>In diesem Artikel wirst du:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Den <code>Sprite2D<\/code> unseres Players durch einen <code>AnimatedSprite2D<\/code> ersetzen.<\/li>\n\n\n\n<li>Mehrere Animationen (z.B. &#8222;idle&#8220;, &#8222;walk&#8220;) in einer <strong>SpriteFrames<\/strong>-Ressource erstellen.<\/li>\n\n\n\n<li>Lernen, wie man <strong>Sprite Sheets<\/strong> effizient importiert, um Animation-Frames zu erhalten.<\/li>\n\n\n\n<li>Das <code>player.gd<\/code> Skript erweitern, um die richtige Animation basierend auf der Bewegung des Players abzuspielen.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Schritt 1: Den Sprite2D durch AnimatedSprite2D ersetzen<\/h3>\n\n\n\n<p>\u00c4hnlich wie bei der M\u00fcnze tauschen wir den einfachen <code>Sprite2D<\/code>-Node unseres Players gegen einen <code>AnimatedSprite2D<\/code> aus.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u00d6ffne deine Szene <strong><code>player.tscn<\/code><\/strong>.<\/li>\n\n\n\n<li>W\u00e4hle im Scene Dock den <strong>Sprite<\/strong>-Node (<strong><code>Sprite2D<\/code><\/strong>) aus, der aktuell ein Kind deines <strong>Player<\/strong>-Node (<code>CharacterBody2D<\/code>) ist.<\/li>\n\n\n\n<li>Klicke mit der rechten Maustaste auf den <strong><code>Sprite2D<\/code><\/strong> Node und w\u00e4hle <strong>&#8222;Change Type&#8220;<\/strong>.<\/li>\n\n\n\n<li>Suche im Suchfeld nach <strong><code>AnimatedSprite2D<\/code><\/strong>, w\u00e4hle ihn aus und klicke <strong>&#8222;Change&#8220;<\/strong>. Benenne ihn um in &#8222;<strong>Animation<\/strong>&#8222;.<\/li>\n\n\n\n<li>Dein <code>Sprite2D<\/code> wurde nun durch einen <code>AnimatedSprite2D<\/code> ersetzt. Ein Warnsymbol zeigt an, dass noch keine Animationen definiert sind.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Schritt 2: Eine neue SpriteFrames-Ressource erstellen und Animationen hinzuf\u00fcgen<\/h3>\n\n\n\n<p>Wir brauchen wieder eine <strong>SpriteFrames<\/strong>-Ressource, um die Animationen f\u00fcr unseren Player zu definieren.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>W\u00e4hle im Scene Dock deinen <strong>Animation<\/strong>-Node (<strong><code>AnimatedSprite2D<\/code><\/strong> aus.<\/li>\n\n\n\n<li>Gehe in den Inspector. Klappe den Abschnitt &#8222;Animation&#8220; (innerhalb von <strong><code>AnimatedSprite2D<\/code><\/strong>) auf.<\/li>\n\n\n\n<li>Du siehst dort die Eigenschaft <strong>&#8222;Sprite Frames&#8220;<\/strong>, die momentan &#8222;&lt;empty&gt;&#8220; ist.<\/li>\n\n\n\n<li>Klicke auf das Dropdown-Men\u00fc neben &#8222;Sprite Frames&#8220; und w\u00e4hle <strong>&#8222;New SpriteFrames&#8220;<\/strong>.<\/li>\n\n\n\n<li>Eine neue <strong>SpriteFrames<\/strong>-Ressource wurde erstellt. Klicke auf das neu erschienene <strong>SpriteFrames<\/strong>-Symbol (da wo gerade noch &lt;empty&gt; stand).<\/li>\n\n\n\n<li>Unten im Editor \u00f6ffnet sich der <strong>SpriteFrames-Editor<\/strong>. Dies ist der Bereich, in dem wir unsere Animationen erstellen und verwalten.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Sprite Sheets importieren<\/h4>\n\n\n\n<p>Die meisten Player-Animationen liegen als sogenannte <strong>Sprite Sheets<\/strong> vor \u2013 gro\u00dfe Bilder, die alle Frames einer oder mehrerer Animationen enthalten. Du kannst z.B. eine Player-Animation als Sprite Sheet von <a href=\"https:\/\/fortwostudio.itch.io\/adventure-boy\">itch.io<\/a> verwenden. Lade sie herunter, entpacke das Zip-Archiv und f\u00fcge die Dateien &#8222;Idle.png&#8220; und &#8222;Walk.png&#8220; dem File-System-Dock im Ordner &#8222;images&#8220; hinzu.<br>Godot macht das Importieren von Frames aus Sprite Sheets sehr einfach:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Im <strong>SpriteFrames-Editor<\/strong> (unten im Editor) siehst du eine Liste deiner Animationen (standardm\u00e4\u00dfig &#8222;default&#8220;). Diese benennen wir um in &#8222;idle&#8220; (Leerlauf).<\/li>\n\n\n\n<li>Auf der rechten Seite, \u00fcber dem Frame-Bereich, findest du den Button <strong>&#8222;Add Frames from Sprite Sheet&#8220;<\/strong> (ein Gitter-Icon mit Plus). Klicke darauf.<\/li>\n\n\n\n<li>W\u00e4hle deine Sprite Sheet-Bilddatei aus (hier also &#8222;Idle.png&#8220;).<\/li>\n\n\n\n<li>Ein <strong>&#8222;Select Frames&#8220;<\/strong>-Fenster \u00f6ffnet sich. Hier kannst du einstellen, wie Godot die Frames aus dem Bild &#8222;schneiden&#8220; soll. \u00dcber &#8222;Auto Slice&#8220; kann der Vorgang in der Regel gut abgek\u00fcrzt werden. Klicke darauf und die Frames werden in Teile \u00e1 510 x 510 px geschnitten.<\/li>\n\n\n\n<li>W\u00e4hle nun alle BIlder von links nach rechts aus. Mit STRG + Mausrad kannst du zoomen, das macht die Auswahl einfacher.<\/li>\n\n\n\n<li>Nachdem du die Fames ausgew\u00e4hlt hast, klicke <strong>&#8222;Add 16 Frame(s)&#8220;<\/strong>. Die Frames werden der aktuell ausgew\u00e4hlten Animation (&#8222;idle&#8220;) hinzugef\u00fcgt.<\/li>\n<\/ol>\n\n\n\n<p>Wenn du einzelne Frame-Bilder hast, kannst du sie auch einfach per Drag-and-Drop aus dem Filesystem Dock in den Frame-Bereich ziehen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Neue Animationen erstellen<\/h4>\n\n\n\n<p>F\u00fcr unseren Player werden wir zwei Animationen hinzuf\u00fcgen: &#8222;idle&#8220; und &#8222;walk&#8220;. <\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Falls noch nicht geschehen, f\u00fcge die Animation f\u00fcr &#8222;idle&#8220; wie oben beschrieben hinzu. <\/li>\n\n\n\n<li>Klicke auf den Button <strong>&#8222;Add Animation&#8220;<\/strong> (das BLatt mit dem Plus-Icon) im <strong>SpriteFrames-Editor<\/strong>, um eine neue Animation zu erstellen. Benenne sie <strong>&#8222;<\/strong>walk&#8220;.<\/li>\n\n\n\n<li>F\u00fcge die Frames f\u00fcr die <strong>&#8222;walk&#8220;<\/strong>-Animation hinzu.<\/li>\n\n\n\n<li>Passe die <strong>&#8222;Speed (FPS)&#8220;<\/strong> f\u00fcr jede Animation an, damit sie fl\u00fcssig aussieht (bei 16 Bildern z.B. 16 FPS). Aktiviere <strong>&#8222;Looping&#8220;<\/strong> f\u00fcr die &#8222;idle&#8220;-Animation, damit sie sich wiederholt.<\/li>\n\n\n\n<li>Stelle au\u00dferdem sicher, dass &#8222;<strong>Autoplay on Load<\/strong>&#8220; f\u00fcr die &#8222;idle&#8220;-Animation aktiviert ist. Diese Einstellung findest du links neben dem &#8222;<strong>Looping<\/strong>&#8222;. <\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Schritt 3: Das Player-Script f\u00fcr Animationssteuerung erweitern<\/h3>\n\n\n\n<p>Jetzt geht es darum, die richtige Animation basierend auf der Bewegung unseres Players abzuspielen. Die Bewegungslogik wird in <code>_physics_process(delta)<\/code> verarbeitet, und dort setzen wir auch die <code>velocity<\/code> des Players. Die Entscheidung, welche Animation laufen soll, h\u00e4ngt direkt von dieser <code>velocity<\/code> ab.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00d6ffne dein <code>player.gd<\/code> Script (es sollte bereits an deinem <strong>Player<\/strong> (<code>CharacterBody2D<\/code>) Node h\u00e4ngen).<\/li>\n\n\n\n<li>Als Erstes brauchen wir eine Referenz auf unseren <code>AnimatedSprite2D<\/code>-Node im Skript. F\u00fcge diese Zeile ganz oben im Skript ein, am besten direkt nach den <code>extends<\/code> und <code>class_name<\/code>-Deklarationen:<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \">class_name Player extends CharacterBody2D\n\n@onready var animation = $Animation # Stelle sicher, dass $AnimatedSprite2D der korrekte Name deines AnimatedSprite2D Nodes ist\n\nvar speed = 200 # Einheit: Pixel pro Sekunde\n# ... (restlicher Code)<\/pre><\/div>\n\n\n\n<p><strong><code>@onready var animated_sprite_2d = $Animation<\/code><\/strong>: Dies ist eine bequeme Methode, um auf Kind-Nodes zuzugreifen. <code>$AnimatedSprite2D<\/code> ist eine Kurzform f\u00fcr <code>get_node(\"Animation\")<\/code>. <code>onready<\/code> stellt sicher, dass die Variable erst initialisiert wird, wenn der Node und seine Kinder in der Szene bereit sind.<strong>Wichtig: <\/strong>Der Name hinter dem $ muss genau der Bezeichnung im Node-Dock entsprechen.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Navigiere zur Funktion <code>_physics_process(delta)<\/code>. Hier werden wir die Logik f\u00fcr die Animationen hinzuf\u00fcgen.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><\/li>\n<\/ol>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:python decode:true \"># player.gd\n# ...\n\n# Called every frame (gut f\u00fcr visuelle Updates)\nfunc _process(delta):\n\t# rotation_degrees += 45 * delta # &lt;&lt;-- diese Zeile kann nun gel\u00f6scht werden\n\tpass\n\nfunc _physics_process(delta):\n    # ... (Dein Bewegungs-Input Code zur Berechnung von 'direction') ...\n\n    velocity = direction * speed\n    move_and_slide()\n\n    # Animationssteuerung\n\tvar anim_name = \"idle\" # Standard-Animation ist \"idle\"\n\n\tif velocity.length() &gt; 0.1: # Pr\u00fcfe, ob sich der Player bewegt\n\t\t# Wenn der Player sich bewegt, spielen wir die \"walk\"-Animation.\n\t\tanim_name = \"walk\"\n        # Da wir nur eine Animation \"nach rechts\" haben, spiegeln wir den Player ggf.\n\t\tif velocity.x &gt; 0:\n\t\t\tanimation.flip_h = false\n\t\telse:\n\t\t\tanimation.flip_h = true\n\n    # Spiele die entsprechende Animation, aber nur, wenn sie nicht bereits l\u00e4uft\n\tif animation.animation != anim_name:\n\t\tanimation.play(anim_name)\n<\/pre><\/div>\n\n\n\n<p><strong>Erkl\u00e4rung des Codes<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong><code>velocity.length()<\/code><\/strong>: Der <code>velocity<\/code>-Vektor hat eine L\u00e4nge, die seiner Geschwindigkeit entspricht. Wenn der Player stillsteht, ist <code>velocity<\/code> ein <code>Vector2.ZERO<\/code>, und <code>length()<\/code> ist <code>0<\/code>. Wenn er sich bewegt, ist <code>length()<\/code> gr\u00f6\u00dfer als <code>0<\/code>. Wir verwenden einen kleinen Schwellenwert (<code>0.1<\/code>), um sicherzustellen, dass wir nicht auf winzige, unmerkliche Bewegungen reagieren.<\/li>\n\n\n\n<li><strong><code>animation: AnimatedSprite2D<\/code><\/strong>: Dies ist die <code>@onready<\/code> Variable, die eine Referenz auf deine Animation enth\u00e4lt.<\/li>\n\n\n\n<li><strong><code>if velocity.x &gt; 0: animation.flip_h = false<\/code><\/strong>: Wenn der Spieler sich nach rechts bewegt (velocity<code>_x<\/code> ist positiv), wollen wir, dass der Sprite normal aussieht, also setzen wir <code>flip_h<\/code> auf <code>false<\/code>.<\/li>\n\n\n\n<li><strong><code>else velocity_x &lt; 0: animation.flip_h = true<\/code><\/strong>: Wenn der Spieler sich nach links bewegt (velocity<code>_x<\/code> ist negativ), wollen wir, dass der Sprite <em>gespiegelt<\/em> wird, also setzen wir <code>flip_h<\/code> auf <code>true<\/code>.<\/li>\n\n\n\n<li><strong><code>animation.animation != anim_name<\/code><\/strong>: Diese Pr\u00fcfung ist wichtig! Sie verhindert, dass wir die <code>play()<\/code>-Methode in jedem einzelnen Frame aufrufen, wenn die gew\u00fcnschte Animation bereits l\u00e4uft. <\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Schritt 4: Speichern und Ausf\u00fchren<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Speichere dein <code>player.gd<\/code> Skript (Strg + S).<\/li>\n\n\n\n<li>Stelle sicher, dass deine <code>player.tscn<\/code> und <code>coin.tscn<\/code> ebenfalls gespeichert sind.<\/li>\n\n\n\n<li>F\u00fchre dein Projekt aus (F5).<\/li>\n<\/ol>\n\n\n\n<p>Jetzt sollte sich dein Player:in bewegen und zwischen &#8222;idle&#8220;- und &#8222;run&#8220;-Animationen wechseln, je nachdem, ob er sich bewegt oder stillsteht! Wenn du separate Richtungsanimationen hinzugef\u00fcgt hast, wird er sogar in die entsprechende Richtung &#8222;laufen&#8220;.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Dein n\u00e4chster Schritt<\/h3>\n\n\n\n<p>Sieht doch gut aus! Du hast gelernt, wie man <code>AnimatedSprite2D<\/code> nutzt, um komplexe Animationen per Skript zu steuern. Das gibt deinem Spiel sofort viel mehr visuelles Feedback und Tiefe.<\/p>\n\n\n\n<p>Als N\u00e4chstes erg\u00e4nzen wir Animationen und Soundeffekte, die abgespielt werden, wenn der Spieler eine M\u00fcnze einsammelt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem unsere M\u00fcnzen nun schick animiert sind, ist der n\u00e4chste logische Schritt, auch unseren Player zu animieren. Dadurch wird das Spielgeschehen noch dynamischer&hellip;<\/p>\n","protected":false},"author":2,"featured_media":631,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33],"tags":[35,43,34,37],"class_list":["post-621","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-godot","tag-2d-game","tag-animation","tag-godot","tag-sprite"],"_links":{"self":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/621","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/comments?post=621"}],"version-history":[{"count":2,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/621\/revisions"}],"predecessor-version":[{"id":632,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/621\/revisions\/632"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/media\/631"}],"wp:attachment":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/media?parent=621"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/categories?post=621"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/tags?post=621"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}