Automatisch spawnen met een Timer
In de vorige les spawn je muntjes bij de start van het level, met vaste coördinaten in _ready(). In deze les laat je het level dat zélf blijven doen terwijl je speelt: elke paar seconden een nieuw muntje, steeds op een andere plek.
Geschreven voor Godot 4.7.x — zie Godot-versies voor compatibiliteit.
Voorspel: hoe doe je "elke 2 seconden"?
Je wilt dat spawn_muntje() elke 2 seconden wordt aangeroepen. Hoe zou Godot dat oplossen? Denk aan wat je in Signals & een muntje oppakken leerde over hoe nodes elkaar iets laten weten.
Antwoord
Met een node en een signal — zoals bijna alles in Godot:
- De node heet
Timer: een onzichtbare stopwatch die telkens opnieuw aftelt. - Zodra de tijd om is, stuurt hij het signal
timeout. Daar koppel je je spawn-functie aan, net zoals jebody_enteredaan het muntje koppelde.
Stap 1: Een Timer toevoegen
- Open
level1.tscn. - Klik met rechts op de root-node → Add Child Node →
Timer. - Stel hem in via de Inspector:
| Eigenschap | Waarde | Betekenis |
|---|---|---|
| Wait Time | 2 | Aantal seconden per aftel-ronde |
| One Shot | uit | Uit = telkens opnieuw aftellen; aan = maar één keer |
| Autostart | aan | Begin met aftellen zodra het level start |
De Timer is onzichtbaar in het spel — het is puur een stopwatch, geen afbeelding.
Stap 2: Koppel het timeout-signal
- Selecteer de
Timerin de Scene Tree. - Ga naar het Node-tabblad rechts naast de Inspector.
- Dubbelklik op
timeout, kies de root-node (metlevel1.gd) als ontvanger en klik op Connect.
Godot voegt deze functie toe aan level1.gd:
func _on_timer_timeout() -> void:
pass # hier komt je code
Deze functie wordt vanaf nu elke 2 seconden aangeroepen.
Stap 3: Een willekeurige plek met randf_range()
Elke keer op exact dezelfde plek spawnen is saai. randf_range() geeft een willekeurig getal tussen twee grenzen:
randf_range(50, 1000)
Elke aanroep levert een ander getal op tussen 50 en 1000 — bijvoorbeeld 312.7, dan 891.2, dan 144.9. Gebruik het als x-coördinaat en elk muntje verschijnt ergens anders:
func _on_timer_timeout() -> void:
spawn_muntje(randf_range(50, 1000), 100)
Vervang 1000 door de breedte van jouw level, en 100 door een hoogte boven je vloer.
Stap 4: Test
Je hele level1.gd ziet er nu zo uit:
extends Node2D
const MUNTJE = preload("res://muntje.tscn")
func _ready() -> void:
spawn_muntje(200, 100)
func spawn_muntje(x: float, y: float) -> void:
var nieuw_muntje = MUNTJE.instantiate()
nieuw_muntje.position = Vector2(x, y)
add_child(nieuw_muntje)
func _on_timer_timeout() -> void:
spawn_muntje(randf_range(50, 1000), 100)
Start met F5 en blijf even kijken: elke 2 seconden verschijnt er ergens een nieuw muntje. Je score kan nu eindeloos oplopen.
De Timer-instellingen staan ook in de Nodes cheatsheet.
Opdracht 8.4.a: spawn ook vijanden
Muntjes verzamelen zonder gevaar is te makkelijk. Laat het level óók vijanden spawnen, langzamer dan de muntjes — bijvoorbeeld één per 5 seconden. Gebruik de vijand-scène uit Opdracht 7.1.a.
Klik hier voor een tip.
Je hebt drie dingen nodig, allemaal een herhaling van deze les:
- Een tweede
constmetpreload("res://vijand.tscn")en een functiespawn_vijand(x, y). - Een tweede
Timer-node — geef hem een duidelijke naam zoalsVijandTimeren een langere Wait Time. - Koppel het
timeout-signal van díe timer; Godot noemt de functie dan_on_vijand_timer_timeout().
Klik hier voor de oplossing.
Voeg een Timer toe, hernoem hem naar VijandTimer, zet Wait Time op 5 en Autostart aan, en koppel timeout aan de root. Breid level1.gd uit:
extends Node2D
const MUNTJE = preload("res://muntje.tscn")
const VIJAND = preload("res://vijand.tscn")
func _ready() -> void:
spawn_muntje(200, 100)
func spawn_muntje(x: float, y: float) -> void:
var nieuw_muntje = MUNTJE.instantiate()
nieuw_muntje.position = Vector2(x, y)
add_child(nieuw_muntje)
func spawn_vijand(x: float, y: float) -> void:
var nieuwe_vijand = VIJAND.instantiate()
nieuwe_vijand.position = Vector2(x, y)
add_child(nieuwe_vijand)
func _on_timer_timeout() -> void:
spawn_muntje(randf_range(50, 1000), 100)
func _on_vijand_timer_timeout() -> void:
spawn_vijand(randf_range(50, 1000), 100)
Elke timer telt onafhankelijk af: muntjes elke 2 seconden, vijanden elke 5.
Er gaat iets mis
Er spawnt helemaal niets
Oorzaak: De Timer telt niet af, of het signal is niet gekoppeld.
Oplossing:
- Selecteer de
Timeren controleer dat Autostart aanstaat. (Zonder Autostart start een Timer pas als je in codestart()aanroept.) - Open het Node-tabblad. Staat er een groen pijltje bij
timeout? - Controleer dat de functienaam in je script exact overeenkomt met wat Godot heeft gekoppeld.
Zelf vinden: zet een print("timer") als eerste regel in _on_timer_timeout. Blijft Uitvoer leeg, dan gaat het om de Timer of het signal en hoef je je spawn-code niet te doorzoeken.
Er spawnt maar één keer iets, daarna niets meer
Oorzaak: One Shot staat aan — de Timer telt dan één keer af en stopt.
Oplossing: Selecteer de Timer en zet One Shot uit in de Inspector.
De muntjes spawnen buiten mijn level of in de grond
Oorzaak: De grenzen van randf_range() of de vaste y-waarde passen niet bij jouw level.
Oplossing: Meet je level na in de editor: selecteer een tegel aan de linker- en rechterrand en lees Position af. Gebruik die x-waarden als grenzen, en een y die ruim boven je vloer ligt.
Staat je fout er niet bij? In Fouten zoeken staat hoe je hem zelf opspoort.