Sari la conținut
EduCamp
Godot / Jocuri Mediu Godot de la zero · partea 5

Monede, semnale și scor

Adaugi monede care dispar când sunt atinse, folosind Area2D și semnale, apoi afișezi scorul pe ecran. Jocul e gata.

50 minute Nivel: Mediu EduCamp

Nume și prenume: ................................................    Clasa: .................    Data: .......................

La finalul fișei, elevul poate:

  • explice ce este un semnal și când este emis
  • construiască o zonă de detecție cu Area2D
  • conecteze semnalul body_entered la o funcție din script
  • păstreze scorul într-o variabilă și să îl afișeze cu un Label

Ai nevoie de:

  • Godot 4
  • Proiectul ColecteazaMonede, cu pereții din fișa 4

Ai un personaj care se mișcă într-o zonă închisă. Îi dăm un scop: să strângă monede.

Cum arată la final

Editorul Godot la finalul fișei: în panoul Scene, Main cu Player, cei patru pereți, cinci monede și ScoreLabel; în Viewport, terenul închis de pereți, cu monedele împrăștiate și scorul în colț

Uită-te aici ori de câte ori nu ești sigur că ai făcut bine: în stânga arborele de noduri, în mijloc cum arată terenul.

1. Semnalul

Până acum, codul tău a întrebat în continuu: „se apasă o tastă? se apasă o tastă?”, de 60 de ori pe secundă.

Pentru unele lucruri asta e risipă. E mai bine să fii anunțat când se întâmplă ceva.

Un semnal este exact acest anunț: un mesaj trimis de un nod atunci când se produce un eveniment.

Area2D este nodul care definește o zonă de detecție. El nu oprește pe nimeni — doar observă cine intră. Când un corp intră în zonă, emite semnalul body_entered.

Moneda va arăta așa:

Coin [Area2D]
├── Imagine [Sprite2D]
└── Coliziune [CollisionShape2D]

Aceeași structură ca la Player, dar cu alt tip de rădăcină: Area2D în loc de CharacterBody2D. Personajul se ciocnește, moneda doar detectează.

2. Construim scena Coin

  1. Scene → New SceneOther Node → caută Area2DCreate.
  2. F2Coin.
  3. Cu Coin selectat: Ctrl+ASprite2DF2Imagine.
  4. Trage icon.svg peste câmpul Texture din Inspector.
  5. La Imagine, deschide Transform și pune Scale 0.12 și 0.12 — moneda e mai mică decât personajul.
  6. Selectează din nou Coin, apoi Ctrl+ACollisionShape2DF2Coliziune.
  7. La Shape alege New CircleShape2D. Deschide Shape și pune Radius 10.
  8. Salvează cu Ctrl+S, sub numele coin.tscn.

3. Scriptul monedei

  1. Cu nodul Coin selectat, apasă Attach Script 📜, lasă numele coin.gd și Create.
  2. Șterge tot și scrie:
extends Area2D

func _on_body_entered(body):
	if body.name == "Player":
		print("Monedă colectată")
		queue_free()
InstrucțiuneaDe unde vineCe face
_on_body_entered(body)chemată de semnaltu scrii conținutul, dar nu o chemi; o cheamă semnalul
bodydat de semnalcorpul care a intrat în zonă
body.nameproprietate din Godotnumele nodului, așa cum apare în panoul Scene
ifcuvânt al limbajuluiexecută ce urmează doar dacă e adevărat
queue_free()funcție a lui Godoto chemi tu; șterge nodul din joc

4. Conectăm semnalul

  1. Selectează nodul Coin.
  2. În panoul din dreapta, lângă Inspector, apasă fila Node, apoi Signals.
  3. În listă găsește body_entered(body: Node2D).
  4. Dublu-clic pe el. Se deschide o fereastră.
  5. Verifică jos, la Receiver Method, că scrie _on_body_entered.
  6. Apasă Connect.

Lângă funcția din script a apărut o iconiță verde 🟢 în marginea din stânga. Înseamnă că semnalul e legat.

5. Punem monedele în joc

  1. Deschide main.tscn.
  2. Trage coin.tscn din FileSystem în Viewport.
  3. Repetă până ai cinci monede, așezate în locuri diferite, între pereți.

Ai grijă ca toate să fie copii direcți ai lui Main, nu ale altui nod:

Main
├── Player
├── WallTop, WallBottom, WallLeft, WallRight
└── Coin, Coin2, Coin3, Coin4, Coin5
  1. Ctrl+S, apoi F5. Treci cu personajul peste fiecare monedă.

Moneda dispare, iar în Output apare Monedă colectată.

6. Scorul

Jocul funcționează, dar nu ține minte nimic. Adăugăm un scor.

Scorul este o informație care se schimbă în timpul jocului, deci îl păstrăm într-o variabilă. Îl afișăm cu un nod Label.

  1. În main.tscn, selectează Main și adaugă un nod Label. F2ScoreLabel.
  2. În Inspector, la Text, scrie Scor: 0.
  3. Deschide Transform și pune Position la (30, 20) — colțul din stânga sus.
  4. Cu Main selectat, apasă Attach Script, lasă numele main.gd, Create.
  5. Scrie:
extends Node2D

var score: int = 0

func add_score():
	score += 1
	$ScoreLabel.text = "Scor: " + str(score)
InstrucțiuneaDe unde vineCe face
scoreales de tinenumele variabilei
: inttip din Godotține numere întregi, fără zecimale
add_score()funcție scrisă de tinenu începe cu _, deci o chemi tu — din coin.gd
score += 1cuvânt al limbajuluiprescurtare pentru score = score + 1
$ScoreLabelscurtătură din Godotgăsește nodul copil cu numele ScoreLabel
.textproprietate din Godottextul afișat de nodul Label
str()funcție a lui Godottransformă numărul în text, ca să poată fi lipit de o frază
  1. Deschide coin.gd și adaugă o linie, înainte de queue_free():
extends Area2D

func _on_body_entered(body):
	if body.name == "Player":
		get_parent().add_score()
		queue_free()

get_parent() este o funcție a lui Godot: întoarce nodul părinte al monedei, adică Main. Pe el chemi apoi add_score(), funcția scrisă de tine în main.gd.

Citit de la stânga la dreapta: ia părintele meu → cheamă-i funcția add_score. Moneda nu ține scorul; îi cere lui Main să-l crească.

  1. Salvează tot și rulează cu F5.

Fiecare monedă colectată crește scorul cu 1.

7. Verificarea finală

De verificatCum
Personajul se mișcă în toate direcțiilesăgețile
Se oprește la toți cei patru perețimergi în fiecare margine
Fiecare monedă dispare o singură datăstrânge-le pe toate
Scorul final este egal cu numărul monedelorcitește eticheta
Nu apar erori roșiiuită-te în Output după ce închizi jocul

Exerciții

🔑 Rezolvare

Nu se întâmplă nimic. Moneda rămâne pe loc, scorul nu crește, iar în Output nu apare nicio eroare.

Codul din funcție e corect, dar funcția nu e chemată niciodată. Godot nu are de unde să știe că tu voiai să o folosească.

De reținut: „nu apare nicio eroare” nu înseamnă „totul e în regulă”. Uneori înseamnă că o parte din cod nici măcar nu rulează.

🔑 Rezolvare

Apare A intrat: Player.

print cu mai multe valori le lipește una după alta — un mod simplu de a vedea ce se întâmplă în cod fără să ghicești.

Această tehnică se numește depanare prin afișare și e prima pe care o încearcă orice programator când ceva nu merge: pune un print și vezi dacă ajunge acolo.

Șterge linia după exercițiu.

🔑 Rezolvare

În coin.gd:

extends Area2D

@export var valoare: int = 1

func _on_body_entered(body):
	if body.name == "Player":
		get_parent().add_score(valoare)
		queue_free()

În main.gd:

func add_score(puncte):
	score += puncte
	$ScoreLabel.text = "Scor: " + str(score)

@export face variabila să apară în Inspector. Selectezi o monedă din main.tscn, îi pui valoare = 5, și doar aceea valorează 5 puncte — fără să scrii cod separat pentru ea.

Este exact felul în care se construiesc jocurile adevărate: o singură scenă, reglată diferit pentru fiecare instanță.

🔑 Rezolvare
extends Node2D

var score: int = 0

func add_score():
	score += 1
	$ScoreLabel.text = "Scor: " + str(score)
	if score == 5:
		$ScoreLabel.text = "Ai câștigat!"

O variantă mai bună nu folosește numărul 5 scris direct, ci numără monedele existente:

if get_tree().get_nodes_in_group("monede").size() == 0:

Pentru asta, fiecare monedă trebuie pusă în grupul monede, din fila Node → Groups. Avantajul: adaugi sau ștergi monede din scenă fără să mai modifici codul.

Ce ai învățat

  • Un semnal este un anunț trimis când se produce un eveniment.
  • Area2D detectează, nu oprește; body_entered se emite la intrarea unui corp.
  • Semnalul trebuie conectat la funcție, altfel funcția nu e chemată niciodată.
  • queue_free() șterge un nod la sfârșitul cadrului.
  • $NumeNod găsește un copil; str() transformă un număr în text.
  • get_parent() urcă un nivel în arbore — de aceea contează unde stă fiecare nod.

Proiectul complet

Main [Node2D]  (main.gd)
├── Player [CharacterBody2D]  (player.gd)
├── WallTop, WallBottom, WallLeft, WallRight [StaticBody2D]
├── Coin ×5 [Area2D]  (coin.gd)
└── ScoreLabel [Label]

Fișierele: main.tscn · player.tscn · coin.tscn · main.gd · player.gd · coin.gd

Ai construit un joc 2D complet, cu scene refolosibile, mișcare, coliziuni, semnale și interfață.

Autor: EduCamp Actualizat: 16 august 2026