Ga naar hoofdinhoud

Score bijhouden in je karakter

Je raapt nu muntjes op, maar je weet niet hoeveel. In deze les voeg je een score toe die elke keer met 1 omhoog gaat als je een muntje raakt.

Godot 4.7

Geschreven voor Godot 4.7.x — zie Godot-versies voor compatibiliteit.

Voorspel: waar leeft de score?​

In welk script zou jij de variabele score aanmaken?

  • In het muntje-script?
  • In het karakter-script?
  • Ergens anders?
Antwoord

Het muntje is geen goede plek: zodra het muntje wordt opgepakt, verdwijnt het via queue_free() — en daarmee ook zijn score-variabele.

Het karakter is een logische plek: de speler "draagt" zijn eigen score. Zolang het karakter bestaat, bestaat de score.

(In de volgende lessen ontdek je dat een nóg betere plek bestaat: een globale variabele die ook tussen scènes overleeft.)

Stap 1: Voeg score toe aan je karakter​

Open het script van je CharacterBody2D en voeg bovenaan een variabele toe:

extends CharacterBody2D

const SPEED = 300.0
const JUMP_VELOCITY = -800.0

var score = 0

# ... rest van je script

Stap 2: Hoog de score op vanuit het muntje​

Open het script van je muntje. In _on_body_entered heb je al een parameter body — dat is de node die het muntje aanraakt (jouw karakter). Vanuit het muntje kun je dus rechtstreeks bij body.score.

extends Area2D

func _on_body_entered(body: Node2D) -> void:
body.score += 1
print("Score: ", body.score)
queue_free()
CodeWat doet het?
bodyDe node die het muntje raakt (jouw karakter)
body.scoreDe score-variabele van die node
body.score += 1Verhoog de score met 1

Stap 3: Test het​

Start het spel met F5 en pak een paar muntjes op. Kijk in Uitvoer onderaan:

Score: 1
Score: 2
Score: 3

Voorspel: hoe krijg ik dit op het scherm?​

Het werkt in Uitvoer, maar je wilt het op het scherm zien. Hoe zou je dat aanpakken?

Bekijk een (broze) poging

Je zou een Label kunnen toevoegen en in een Label-script proberen het karakter op te zoeken:

extends Label

func _process(delta: float) -> void:
text = "Score: " + str(get_node("../CharacterBody2D").score)

Maak je geen zorgen als _process en str nieuw zijn — die komen in Score op het scherm tonen aan bod. Dit voorbeeld is alleen om de pijn te laten zien.

Dit werkt — zolang je karakter precies CharacterBody2D heet en op de juiste plek in de Scene Tree staat. Verschuif of hernoem je iets, of laad je een nieuw level? Crash. In de volgende les (Global variables) zie je een schonere oplossing.

Opdracht 7.2.a: levens met Game Over​

Je hebt nu een score in je karakter. Voeg er een levens-systeem aan toe en laat het spel reageren als ze op zijn.

  1. Voeg var levens = 3 toe aan je karakter.
  2. Laat de vijand (uit Signals & muntje) bij contact body.levens -= 1 doen en de waarde printen.
  3. Nieuw: als body.levens op 0 (of lager) komt, print "GAME OVER" in Uitvoer en sluit het spel met get_tree().quit().
Klik hier voor een tip.
  • Voeg var levens = 3 toe onder var score = 0 in je karakter-script.
  • Open je vijand-script.
  • Pas _on_body_entered aan zodat hij eerst body.levens -= 1 doet en print.
  • Voeg een if-blok toe: if body.levens <= 0: met daarbinnen de print en get_tree().quit().
  • Let op de indentatie: alles binnen het if-blok moet één tab inspringen.
Klik hier voor de oplossing.

In je karakter-script:

extends CharacterBody2D

const SPEED = 300.0
const JUMP_VELOCITY = -800.0

var score = 0
var levens = 3

# ... rest van je script

In je vijand-script:

extends Area2D

func _on_body_entered(body: Node2D) -> void:
body.levens -= 1
print("Levens: ", body.levens)

if body.levens <= 0:
print("GAME OVER")
get_tree().quit()

queue_free()

get_tree().quit() sluit het hele spel-venster. In een echte game zou je hier een Game Over-scherm laten zien — dat leer je later. Voor nu zie je in elk geval dat de check werkt.

Er gaat iets mis​

Foutmelding: Invalid access to property or key 'score' on a base object of type 'TileMapLayer'.

Oorzaak: Je muntje raakt de grond. Voor een Area2D is je TileMapLayer met collision ook een body, dus _on_body_entered krijgt dan de grond in plaats van je karakter. De grond heeft geen score. Achteraan de melding staat wat body was: TileMapLayer.

Zo zie je de melding zelf, met een muntje dat de grond als body krijgt:

# FOUT
extends Area2D

func _ready() -> void:
_on_body_entered(TileMapLayer.new())

func _on_body_entered(body: Node2D) -> void:
body.score += 1

Oplossing: Zet het muntje iets hoger, zodat zijn CollisionShape2D de tegels niet raakt. Wil je zeker zijn dat alleen je karakter telt, zet dan if body is CharacterBody2D: boven de regel met score en laat die regel eronder inspringen.

Mijn score begint elke keer weer bij 0 als ik het spel herstart

Oorzaak: Bij opnieuw starten wordt het karakter opnieuw aangemaakt, en dus ook var score = 0. De score leeft maar zolang het karakter bestaat.

Oplossing: Dit lossen we op in Global variables — variabelen die buiten één node leven.