Comme expliqué en introduction, nous allons utiliser le langage GDScript intégré à Godot. Le GDScript est un langage dynamique orienté objet, à la syntaxe similaire à Python. Le langage est étroitement intégré au moteur, le rendant particulièrement agréable à utiliser.
Documenation : https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html
Les variables sont dynamiques, une fois une variable déclarée on peut lui assigner n’importe quelle valeur de n’importe quel type. Il est néanmoins possible (et recommandé) de typer les variables statiquement, en précisant le type à la déclaration.
# Déclaration sans initialisation
var my_variable # null par défaut
# Déclaration avec initialisation
var my_variable_initialized = "une mangue"
# Déclaration avec typage statique et initialisation
var my_variable_initialized_typed: Vector2 = Vector2(1, 0)
# Déclaration d'une constante, sa valeur ne pourra pas être modifiée ultérieurement
const MY_CONSTANT: float = 4.2 # Tableaux
var tableau_mixte = ["Godot", 4.2, true]
var tableau_type: Array[int] = [2, 0, 2]
tableau_type.append(5)
print(tableau_mixte[1]) # affiche 4.2
print(tableau_type) # Affiche [2, 0, 2, 5]
# Dictionnaires
var bazar = {
"key": 3629,
5: "le nombre cinq",
"tableau": [1,2,3,4]
}
var descriptions: Dictionary[String, String] = {
"sword" : "Awesome combat sword",
"shield" : "Rusty useless shield",
"coffe" : "COFFE? WHERE? I NEED IT."
}if score > high_score and not is_in_godmode:
score = high_score
print("Bravo!")
if result >= 0.5:
print("This is great!")
elif result >= 0.25:
print("Things are going side ways...")
else:
print("We are doomed!")# Boucles for
for i in range(10):
print(i)
var liste: Array[String] = ["Rubika", "Game", "Programming"]
for mot in liste:
print(mot)
# Boucle while
var counter: int = 0
while counter < 10 :
print(counter)
counter += 1func get_welcome_prompt() -> String:
return "WELCOME $> "
func print_n_time(n: int, message: String) -> void:
for i in range(n):
print(message)Les annotations en GDScript sont des mots-clés
précédés du symbole @ qui jouent de rôle de modificateur.
Elles permettent d’indiquer à l’éditeur comment traiter notre code, par
exemple, pour exposer des variables dans l’inspecteur. Nous verrons les
annotations les plus courantes dans les sections suivantes.
Dans Godot, chaque noeud peut avoir un script qui définit son
comportement. Un noeud ne peut avoir qu’un seul script attaché à la
fois. Le script hérite toujours d’une classe de noeud (comme
Node2D, CharacterBody2D, etc.) et peut
redéfinir des fonctions virtuelles pour réagir aux événements du
moteur.
Voici un exemple de script simpliste pour un personnage en vue du dessus top-down.
extends CharacterBody2D
@export var speed: float = 200
func _ready() -> void:
motion_mode = CharacterBody2D.MOTION_MODE_FLOATING
$AnimationPlayer.play("spawn")
func _physics_process(delta: float) -> void:
var direction = Input.get_vector(
"move_west",
"move_east",
"move_noth",
"move_south",
)
move_and_slide(direction * speed)Le moteur appelle automatiquement certaines fonctions spéciales durant le cycle de vie d’un noeud. Ces fonctions, dites virtuelles, peuvent être redéfinies dans votre script pour contrôler le comportement du noeud.
Voici les quatres fonctions les plus communément utilisées :
_ready() : Appelée une seul fois, au
momeent où le noeud est “prêt”. C’est à dire quand lui et tout ses
enfants sont rentré dans l’arbre du jeu. Idéal pour
l’initialisation._input(event) : Appelée à chaque
événement d’entrée (clavier, souris, etc.)._process(delta) : Appelée à chaque
frame. delta représente le temps écoulé depuis la dernière
frame._physics_process(delta) : AppelĂ©e Ă
intervalle fixe (60 FPS par défaut), utilisé pour la physique.C’est grosso-modo le même principe que Awake,
Update, FixedUpdate etc. dans
Unity.
Comme expliqué dans Noeuds et Scènes, les noeud peuvent être accédés à l’aide de chemins, comme pour des fichiers.
Pour ce faire nous allons utiliser la fonction
get_node(path) ou plutĂ´t le racourci $.
func _ready() -> void:
# Accès à noeud via get_node
var animation_player: AnimationPlayer = get_node("Zone/AnimationPlayer")
animation_player.play()
# Accès à noeud en utilisant la syntaxe $ (équivalent à get_node)
var collision: CollisionShape2D = $Zone/Collision
collision.disabled = trueclass_namePar défaut, les scripts GDScript sont anonymes.
L’annotation class_name permet de donner un nom global Ă
votre classe, la rendant accessible partout dans votre projet et visible
dans l’éditeur.
class_name Player
extends CharacterBody2D
@export var speed: float = 300Une fois nommée, vous pouvez référencer cette classe dans d’autres scripts et elle apparaîtra dans la liste des types disponibles lors de la création de noeuds.
L’opérateur as permet de caster une variable
vers un certain type. Si la conversion échoue, la variable vaudra
null.
func _ready() -> void:
var node = get_node("Player")
var player := node as Player
if player:
player.speed = 300L’opérateur := permet de déduire automatiquement le type
de la variable à partir de sa valeur d’initialisation, évitant ainsi de
répéter le type explicitement.
Les getters et setters permettent d’exécuter du code personnalisé lors de la lecture ou de l’écriture d’une variable. C’est utile pour valider des valeurs, déclencher des événements ou mettre à jour l’interface.
var health: int = 100:
set(value):
health = clamp(value, 0, 100)
update_health_bar()
get:
return health
var speed: float = 200.0:
set(value):
if speed < 0:
get_tree().quit() # negative speed is punished by closing the game
speed = value
var is_alive: bool:
get:
return health > 0
func update_health_bar() -> void:
$HealthBar.value = health@exportL’annotation @export permet d’exposer des variables dans
l’inspecteur de Godot, les rendant modifiables
directement depuis l’éditeur sans toucher au code.
@export_group("Stats")
@export var health: int = 100
@export var speed: float = 200.0Vous pouvez également exporter des références directes aux noeuds, évitant ainsi l’utilisation de chemins :
@export var animation_player: AnimationPlayer
@export var sprite: Sprite2D
func _ready() -> void:
# Plus besoin de $AnimationPlayer
animation_player.play("idle")
sprite.modulate = Color.RED@toolL’annotation @tool rend un script exécutable dans
l’éditeur, avant même de lancer le jeu. C’est utile pour créer des
outils personnalisés ou visualiser des changements en temps réel.
@tool
extends Node2D
@export var radius: float = 50.0:
set(value):
radius = value
resize()
func resize() -> void:
var shape := $Collision.shape as CircleShape2D
shape.radius = radiusAvec @tool, votre code s’exécute dans l’éditeur, c’est
très puissant mais c’est aussi un moyen de se tirer une balle dans le
pied, donc à utiliser avec précaution.
preloadLa fonction preload charge une resource au moment de la
compilation du script, garantissant qu’elle est disponible
immédiatement.
const BULLET_SCENE = preload("res://scenes/bullet.tscn")
const EXPLOSION_SOUND = preload("res://sounds/explosion.wav")
func shoot() -> void:
var bullet = BULLET_SCENE.instantiate()
add_child(bullet)Pour un chargement dynamique (au moment de l’exécution), utilisez
plutĂ´t load().
L’inconvénient de preload est qu’il rend le temps de
chargement initial plus long, mais load, qui réalise le
chargement sur le moment mĂŞme, peut produire des lags.
Dans des scénarios plus compliqué, on pourra utiliser des methodes de
chargement de ResourceLoader et afficher une barre de
chargement.
queue_free et freeQuand un noeud n’est plus nécessaire, il faut le supprimer pour libérer la mémoire.
queue_free() : Supprime le noeud Ă la
fin de la frame actuelle (méthode recommandée)free() : Supprime le noeud
immédiatement (peut causer des bugs si d’autres scripts y font encore
référence)func destroy_enemy() -> void:
queue_free() # Supprime l'ennemiPour améliorer la lisibilité du code je vais vous demander de suivre des conventions de nommage “officielles” :
snake_case
(ex: player_health, is_enabled)UPPER_SNAKE_CASE (ex:
MAX_HEALTH, GRAVITY)PascalCase (ex:
AnimatedButton, Enemy)PascalCase (ex:
Player, MainMenu)Pour encore plus de propreté je vous invite à installer le formatteur GDScript, téléchargeable ici : https://github.com/GDQuest/GDScript-formatter/releases
@export aux chemins de noeuds
pour éviter les erreurs si vous renommez des noeuds.