Sound und visuelles Feedback

Unser Spiel nimmt immer mehr Form an! Die Münzen sind animiert und unser Player bewegt sich geschmeidig. Aber noch fehlt etwas, um das Einsammeln der Münzen wirklich befriedigend zu machen: Sound und ein visueller Effekt.

In diesem Artikel werden wir:

  • Einen Sound abspielen, wenn eine Münze eingesammelt wird.
  • Eine neue Animation oberhalb der bestehenden Player-Animation abspielen, um das Einsammeln der Münze zusätzlich hervorzuheben.

Schritt 1: Einen Sound für die Münze hinzufügen

Soundeffekte sind entscheidend für das Spielerlebnis. Ein kurzer „Klingeln“-Sound, wenn eine Münze gesammelt wird, gibt sofortiges Feedback. In Godot nutzen wir dafür den Node AudioStreamPlayer2D.

  1. Füge einen Sound-Node zur Münze hinzu:
    • Öffne deine Szene coin.tscn.
    • Wähle im Scene Dock deinen Coin (Area2D) Node aus.
    • Klicke auf den „+“ Button (Kind-Node hinzufügen).
    • Suche und wähle AudioStreamPlayer2D. Klicke „Create“. Benenne ihn zum Beispiel in CollectSound um.
  2. Lade eine Sounddatei:
    • Gehe in den FileSystem-Dock und erstelle einen neuen Ordner „sounds„.
    • Suche dir eine Sound-Datei aus (z.B. ein Sound-Effekt von itch.io), lade sie herunter und entpacke sie. Danach ziehe die ausgewählte Datei in den FileSystem-Dock in den gerade erstellen Ordner „sounds„.
    • Wähle den neuen CollectSound Node im Scene Dock aus.
    • Gehe in den Inspector. Du siehst dort die Eigenschaft „Stream“, die momentan „<empty>“ ist.
    • Klicke auf das Dropdown-Menü neben „Stream“ und wähle „Load“. Navigiere zu deiner Sounddatei und wähle sie aus.
  3. Spiele den Sound im Script ab:
    • Öffne dein coin.gd Script.
    • Finde die Funktion _on_Coin_body_entered(body).
    • Wir müssen den Sound-Node in unserem Script referenzieren, um ihn abzuspielen. Füge dazu die folgende Zeile oben im Script ein, ähnlich wie du es für AnimatedSprite2D gemacht hast:
  • Jetzt kannst du collect_sound.play() aufrufen, bevor die Münze entfernt wird.

Dein _on_Coin_body_entered sollte nun so aussehen:

Darauf achten: queue_free() und Sound

Wenn du queue_free() aufrufst, wird der Node am Ende des aktuellen Frames aus der Szene entfernt. AudioStreamPlayer2D Nodes spielen ihren Sound nicht mehr weiter, wenn er entfernt wird. Da er ein Child-Node unseres Coins ist, würde der Sound also sofort wieder enden.
Wir warten mit await sound.finished bis der Soundeffekt fertig abgespielt wurde. Erst dann rufen wir queue_free() auf.

Das ist wichtig, da wir die Münze sofort verschwinden lassen wollen, der Sound aber komplett abgespielt werden soll.

Schritt 2: Eine Sammel-Animation für den Player hinzufügen

Neben dem Sound können wir auch eine kurze Animation am Player abspielen, die signalisiert, dass etwas eingesammelt wurde. Diese Animation soll kurz über der normalen Lauf- oder Idle-Animation erscheinen. Dafür nutzen wir einen zweiten AnimatedSprite2D am Player.

  1. Füge einen zweiten AnimatedSprite2D zum Player hinzu:
    • Öffne deine Szene player.tscn.
    • Wähle im Scene Dock deinen Player (CharacterBody2D) Node aus.
    • Klicke auf den „+“ Button (Kind-Node hinzufügen).
    • Suche und wähle AnimatedSprite2D. Klicke „Create“.
    • Benenne diesen neuen Node in AnimatioEffect um, um ihn von deinem bestehenden Player-Animations-Node zu unterscheiden.
  2. Erstelle eine neue SpriteFrames-Ressource für die Sammel-Animation:
    • Suche dir eine weitere Animation aus (z.B. einen Effekt von OpenGameArt.org), lade sie herunter und entpacke sie. Danach ziehe die Datei 0 – 14 in den FileSystem-Dock in den Ordner „images„.
    • Wähle den AnimationEffect Node im Scene Dock aus.
    • Gehe in den Inspector. Erstelle eine „New SpriteFrames“ Ressource für die Eigenschaft „Sprite Frames“.
    • Klicke auf das SpriteFrames-Drop-Down um den Sprite-Frame-Editor zu öffnen.
    • Benenne die Animation „default“ um in „collect“.
    • Füge Frames hinzu, die den kurzen visuellen Effekt für das Einsammeln darstellen sollen. Achte darauf, dass diese Animation NICHT loopend ist (Loop deaktivieren) und stelle eine angemessene „Speed (FPS)“ ein (z.B. 15 FPS für die 15 Bilder des verlinkten Effekts).
    • Optional: du kannst die Größe der Animation im Viewport anpassen.
  3. Spiele die Animation im Player-Script ab:
    • Öffne dein player.gd Script.
    • Referenziere den neuen CollectAnimation Node, ähnlich wie du es für die erste Animation gemacht hast:
  • In der collect_coin() Funktion, die aufgerufen wird, wenn das Münz-Signal empfangen wird, können wir nun diese neue Animation starten.

Deine collect_coin()-Funktion sollte nun so aussehen:

Darauf achten: Überlappende Animationen

Indem wir einen separaten AnimatedSprite2D für die Sammel-Animation verwenden, kann dieser Effekt über dem Spieler abgespielt werden. Die Reihenfolge der Nodes im Scene-Node steuert dabei die Sichtbarkeit. Je weiter untenim Scene Tree steht, desto später wird er in die Szene gezeichnet.

Schritt 3: Sammel-Animation nach Beendigung ausblenden

Damit unsere Sammel-Animation nicht einfach stehen bleibt, nachdem sie abgespielt wurde, blenden wir sie wieder aus. AnimatedSprite2D Nodes haben ein sehr nützliches Signal namens animation_finished(), das ausgelöst wird, sobald eine nicht-loopende Animation beendet ist.

  1. Verbinde das animation_finished()-Signal der CollectAnimation:
    • Öffne deine Szene player.tscn.
    • Wähle im Scene Dock den AnimationEffect Node aus.
    • Gehe ins Node Dock (neben dem Inspector).
    • Suche im Tab „Signals“ das Signal animation_finished().
    • Klicke doppelt darauf oder wähle es aus und klicke „Connect…“.
    • Im „Connect a Signal“-Fenster sollte der Player als „Receiver“ ausgewählt sein. Die Methode sollte _on_animation_effect_animation_finished lauten.
    • Klicke „Connect“. Godot erstellt die Funktion in deinem player.gd Script.
  2. Implementiere die Ausblend-Logik im Player-Script:
    • Öffne dein player.gd Script.In der neu erstellten Funktion _on_animation_effect_animation_finished() blenden wir den CollectAnimation-Node einfach wieder aus.
    Dein player.gd Script sollte nun diese neue Funktion enthalten:

Darauf achten: animation_finished() vs. animation_looped()

AnimatedSprite2D Nodes bieten zwei wichtige Signale, die sich auf den Status der Animation beziehen:

  • animation_finished(): Dieses Signal wird einmalig ausgelöst, wenn eine Animation ihr Ende erreicht hat. Es wird nur für Animationen, die nur einmal abgespielt werden sollen (z.B. ein Sammel-Effekt, ein Treffer, ein Tod), und deren Loop-Eigenschaft im SpriteFrames-Editor auf false gesetzt ist, ausgeführt.
  • animation_looped(): Dieses Signal wird jedes Mal ausgelöst, wenn eine Animation einen vollständigen Durchlauf abgeschlossen und erneut begonnen hat. Es wird nur für Animationen, die in einer Endlosschleife laufen (wie die Idle- oder Lauf-Animation unseres Players, deren Loop-Eigenschaft auf true gesetzt ist) und du auf jeden Zyklus reagieren möchtest (z.B. einen Schritt-Sound nach jedem Schritt-Zyklus abspielen), ausgeführt.

Für unsere CollectAnimation, bei der die Loop-Eigenschaft im SpriteFrames-Editor auf false gesetzt ist, ist animation_finished() die richtige Wahl.

Schritt 4: Speichern und Testen

  1. Speichere deine Szene player.tscn (Strg + S).
  2. Speichere dein player.gd Skript (Strg + S) und dein coin.gd Skript (Strg + S).
  3. Führe dein Projekt aus (F5).

Jetzt sollte dein Player beim Einsammeln einer Münze nicht nur einen Sound abspielen, sondern auch eine zusätzliche, kurze Animation zeigen!


Dein nächster Schritt

Wir haben unseren Interaktionen Sound und zusätzliche visuelle Effekte hinzugefügt, was das Spielerlebnis deutlich verbessert. Du hast gelernt, wie man:

  • AudioStreamPlayer2D Nodes für Soundeffekte einsetzt.
  • Mehrere AnimatedSprite2D Nodes an einem Charakter verwendet, um überlappende Animationen zu erzeugen.
  • Dafür sorgt, dass Animationen ausgeblendet werden, nachdem sie abgespielt wurden.

Als Nächstes werden wir unser Spiel noch dynamischer gestalten, indem wir einen Partikeleffekt erzeugen, wenn eine Münze eingesammelt wird. Das führt uns in die Welt der CPUParticles2D Nodes und deren Konfiguration.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..