Signals & een muntje oppakken
Tijd om iets te kunnen verzamelen in je level. In deze les bouw je een muntje als losse scène en laat je het verdwijnen zodra je karakter het aanraakt. Daarvoor gebruik je signals — Godot's manier om nodes met elkaar te laten praten zonder dat ze elkaar hoeven op te zoeken.
Geschreven voor Godot 4.5.x — zie Godot-versies voor compatibiliteit.
Voorspel: zonder signals?
Stel je hebt twee losse scripts: één voor je muntje, één voor je karakter. Het muntje moet verdwijnen als het karakter het raakt.
Hoe zou jij dat aanpakken zónder signals?
Antwoord
Zonder signals zou het karakter het muntje moeten opzoeken:
# In het karakter-script
var muntje = get_node("Muntje")
muntje.queue_free()
Maar dan moet het karakter weten dát het muntje bestaat, hoe het heet en waar het staat. Heb je meerdere muntjes, of is er al eentje weg, dan crasht je code. Signals lossen dat op: het muntje reageert zelf op de botsing, zonder dat het karakter er iets van hoeft te weten.
Wat zijn signals?
Een signal is een bericht dat een node verstuurt zodra er iets gebeurt. Andere nodes (of de node zelf) kunnen naar dat bericht luisteren en daarop reageren. Denk aan een deurbel:
- De deurbel stuurt een signaal als iemand erop drukt.
- Jij luistert naar dat signaal en doet de deur open.
In Godot is het precies zo: een node stuurt een signal, een andere node vangt het op en voert code uit.
Stap 1: Maak een muntje-scène
- Ga naar Scene → New Scene.
- Kies Other Node en zoek naar
Area2D.Area2Dis een node die botsingen kan detecteren zonder zelf physics te krijgen (geen zwaartekracht, niet wegrollen). - Hernoem de
Area2DnaarMuntje.
Stap 2: Voeg een sprite toe
- Klik met rechts op
Muntje→ Add Child Node. - Voeg een
Sprite2Dtoe. - Sleep je muntje-afbeelding naar Texture in de Inspector.
Stap 3: Voeg een collision shape toe
Zonder collision shape kan Godot geen botsing detecteren.
- Klik met rechts op
Muntje→ Add Child Node. - Voeg een
CollisionShape2Dtoe. - Kies in de Inspector bij Shape een vorm (bijvoorbeeld
CircleShape2D). - Pas de grootte aan zodat de cirkel netjes om het muntje past.
Je Scene Tree ziet er nu zo uit:
Muntje (Area2D)
├── Sprite2D
└── CollisionShape2D
Sla de scène op als muntje.tscn (Ctrl + S).
Stap 4: Koppel een script en het signal
- Selecteer de
Muntje-node. - Klik op het script-icoontje of klik met rechts → Attach Script → Create.
- Ga naar het Node-tabblad (rechts naast de Inspector).
- Dubbelklik op
body_entered. - Kies de
Muntje-node als ontvanger en klik op Connect.
body_entered is een ingebouwd signal van Area2D. Het wordt verstuurd zodra een fysiek lichaam (zoals je CharacterBody2D) het muntje raakt.
Godot maakt automatisch een functie aan in je script:
func _on_body_entered(body: Node2D) -> void:
pass # hier komt je code
Stap 5: Laat het muntje verdwijnen
Vervang de pass door:
extends Area2D
func _on_body_entered(body: Node2D) -> void:
print("Muntje opgepakt!")
queue_free()
| Code | Wat doet het? |
|---|---|
_on_body_entered(body) | Wordt aangeroepen bij een botsing |
body | De node die het muntje raakt (jouw karakter) |
queue_free() | Verwijdert deze node (het muntje) uit het spel |
Stap 6: Plaats het muntje in je level
- Open je level/world-scène.
- Sleep
muntje.tscnvanuit het FileSystem-paneel naar je level. - Plaats het waar je wilt.
- Sleep meerdere keren om meerdere muntjes neer te zetten.
Start het spel met F5, loop tegen een muntje aan en kijk in Uitvoer: het muntje verdwijnt en je ziet "Muntje opgepakt!".
Opdracht 6.1.a: voeg een vijand toe
Je weet nu hoe een muntje op een botsing reageert. Pas hetzelfde principe toe op een vijand.
Maak een vijand-scène. Als de speler de vijand raakt, drukt de vijand een bericht af in Uitvoer en verdwijnt daarna.
Klik hier voor een tip!
- Gebruik dezelfde structuur als het muntje: een
Area2DmetSprite2DenCollisionShape2D. - Koppel het
body_entered-signal aan een functie in het vijand-script. - Gebruik
print()voor een bericht enqueue_free()om de vijand te laten verdwijnen.
Klik hier voor de oplossing!
Scène-structuur (vijand.tscn):
Vijand (Area2D)
├── Sprite2D
└── CollisionShape2D
Script (vijand.gd):
extends Area2D
func _on_body_entered(body: Node2D) -> void:
print("Geraakt door vijand!")
queue_free()
Stappen:
- Maak een nieuwe scène met
Area2Dals root, hernoem naarVijand. - Voeg
Sprite2DenCollisionShape2Dtoe. - Voeg een script toe en koppel
body_entered. - Schrijf de bovenstaande code.
- Sla op als
vijand.tscnen sleep hem in je level.
In de volgende les bouw je een score-teller in je karakter, zodat opgepakte muntjes ook echt geteld worden.
Er gaat iets mis
Mijn karakter loopt door het muntje heen zonder dat het verdwijnt
Oorzaak: Het signal is niet (correct) gekoppeld, of het muntje heeft geen werkende CollisionShape2D.
Oplossing — loop deze checklist langs:
- Selecteer het muntje en open het Node-tabblad. Staat er bij
body_enteredeen groen pijltje (= verbonden)? - Heeft het muntje een
CollisionShape2Dals child? - Heeft die
CollisionShape2Dook echt een Shape ingesteld (bijvoorbeeldCircleShape2D)?
Ik krijg een fout: signal already connected
Oorzaak: Je hebt het body_entered-signal twee keer gekoppeld aan dezelfde functie.
Oplossing:
- Selecteer de
Muntje-node. - Open het Node-tabblad.
- Klik met rechts op de dubbele verbinding onder
body_entered→ Disconnect.
_on_body_entered wordt nooit aangeroepen
Oorzaak: Het muntje is geen Area2D, of de CollisionShape2D heeft geen Shape.
Oplossing:
- Controleer in de Scene Tree dat de root van je muntje een
Area2Dis (nietNode2D). - Selecteer de
CollisionShape2Den stel in de Inspector een Shape in als die nog leeg is.