Pour commencer, téléchargez le projet de départ.
Pour ce premier exercice, nous allons nous amuser avec la physique de Godot.
Le projet est un petit jeu physique dans lequel une balle roule sur des plateformes.
Il est basé sur les assets libres de droit Rolling Ball Assets de Kenney.
Le projet de départ contient déjà :
ball.tscn), dont le
noeud racine est un RigidBody2D.corner_block.tscn), dont le noeud racine est un
StaticBody2D.world.tscn), qui
contient une balle et deux plateformes.NâhĂ©sitez pas Ă me solliciter si vous ĂȘtes bloquĂ©s, si quelque chose nâest pas clair ou si vous avez besoin que je rĂ©explique quelque chose. Ăa pourrait ĂȘtre utile Ă tout le monde !
Avant de commencer Ă pratiquer, prenez le temps de regarder ce qui existe :
world.tscn et regardez ce quâelle
contient.ball.tscn et regardez de quoi elle est
composée.corner_block.tscn et regardez de quoi
elle est composée.F5) et regardez
ce qui se passe.Vous devriez remarquer deux problĂšmes : la balle traverse les plateformes, et elle sort de lâĂ©cran sans que rien ne la suive.
La balle nâa pas de collision, câest pour ça quâelle traverse tout ce quâelle rencontre.
CollisionShape2D en enfant du noeud
racine.CircleShape2D et ajustez son rayon pour
quâelle recouvre la balle.
Tant quâun corps physique nâa pas de forme de collision, Godot affiche un triangle dâavertissement Ă cĂŽtĂ© du noeud. Pensez Ă les surveiller !
Pour visualiser les collisions pendant lâexĂ©cution, activez Debug > Visible Collision Shapes.
Relancez le jeu : la balle ne devrait plus traverser les plateformes.
Ă prĂ©sent, il faut que la vue suive la balle quand elle sort de lâĂ©cran.
Camera2D en enfant de la balle.zoom.
Comme la caméra est enfant de la balle, sa position
est relative Ă celle de la balle (câest le principe des transformations
hiérarchiques). En revanche, elle ne tourne pas avec la balle, car sa
propriété Ignore Rotation est activée par défaut.
Pour aller plus loin, vous pouvez activer Position Smoothing sur la caméra pour adoucir ses mouvements.
CrĂ©ez une nouvelle scĂšne (prefab) pour un bloc qui tourne sur lui-mĂȘme.
Le noeud racine de la scĂšne sera un AnimatableBody2D
(voir documentation).
AnimatableBody2D agit comme le StaticBody2D
utilisĂ© pour les plateformes immobiles, mais peut ĂȘtre dĂ©placĂ© via du
code ou une animation. Il affecte alors les autres
corps, comme le RigidBody2D utilisé pour la balle.
Ajoutez ensuite :
Un Sprite2D en enfant, avec la texture de la
plateforme tournante (block_rotate*.png).
Un CollisionPolygon2D en enfant, dont vous créerez
le polygone en passant par la barre dâoutils.
à présent, on veut faire tourner la plateforme. Pour cela, nous allons ajouter ce comportement via un script.
_physics_process,
puis modifiez-y la propriété rotation à chaque
frame.La méthode _physics_process est appelée automatiquement
Ă chaque frame physique par le moteur, et son
paramÚtre delta correspond au temps écoulé
depuis la frame prĂ©cĂ©dente (en secondes). Câest lâĂ©quivalent de
FixedUpdate dans Unity.
Voici une premiĂšre version possible (loin dâĂȘtre parfaite) :
extends AnimatableBody2D
func _physics_process(delta):
rotation += 1.0 * deltaEn multipliant la vitesse par delta, la plateforme
tourne Ă la mĂȘme vitesse quel que soit le nombre
dâimages par seconde. On dĂ©crit donc la vitesse de rotation en fonction
du temps.
La propriété rotation est exprimée en
radians.
Normalement, tout est bon : vous pouvez tester la plateforme.
Pour le moment, toutes les plateformes tournent Ă la mĂȘme vitesse, et changer cette vitesse oblige Ă modifier le script.
Nous allons donc exposer la vitesse dans
lâinspecteur, grĂące Ă une variable marquĂ©e
@export.
rotation_speed
précédée de @export._physics_process.La syntaxe pour déclarer une variable exportée :
@export var <nom_de_la_variable>: <type_de_la_variable> = <valeur_par_défaut>Dans notre cas, <type_de_la_variable> sera
float.
Une valeur nĂ©gative fait tourner la plateforme dans lâautre sens.
Lâimage de la plateforme comporte des flĂšches qui indiquent son
sens de rotation.
Mais Ă lâheure actuelle, elle nâest pas cohĂ©rente avec le mouvement.
Pour corriger ça, il faut retourner lâimage (flip) :
Sprite2D et utilisez la propriété
flip_h pour corriger ça.flip_h est activĂ©, lâimage est affichĂ©e en
miroir.On veut à présent que ce paramÚtre change en fonction du sens de rotation de la plateforme :
flip_h = true.flip_h = false.On va donc ajouter ce comportement dans le script.
Tout dâabord, il faut que le script puisse accĂ©der au
sprite.
Nous allons utiliser une variable exposée avec @export pour
référencer le noeud directement depuis
lâinspecteur.
Voici les étapes à suivre :
Sprite2D.Sprite2D
depuis lâarbre de la scĂšne vers cet emplacement._ready, modifiez la propriĂ©tĂ©
flip_h du sprite en fonction du signe de
rotation_speed.La syntaxe pour déclarer une référence exportée :
@export var sprite: Sprite2D
Pour tester, placez deux plateformes dans la scĂšne
World et donnez une vitesse positive Ă
lâune dâelles et nĂ©gative Ă lâautre.
Vérifiez ensuite que le visuel est bien retourné en fonction de la
vitesse de rotation.
Pourquoi utiliser @export plutĂŽt quâun chemin Ă©crit en
dur dans le script (comme $Sprite2D) ?
Les variables exportĂ©es sont assignĂ©es avant lâappel
de _ready, vous pouvez donc les utiliser dĂšs cette
méthode.
Si vous oubliez dâassigner le noeud dans lâinspecteur, la variable
vaut null et le jeu plantera avec une erreur au moment
dâaccĂ©der au sprite.
Pour le moment, la balle tombe toute seule dÚs le lancement du jeu. Nous allons rendre le jeu interactif : la balle reste immobile au départ, on vise avec la souris en maintenant le clic, et on la lance en relùchant.
Pour que la balle ne bouge pas au lancement, il faut la geler.
RigidBody2D).freeze.Un corps gelĂ© nâest plus affectĂ© par la physique : il ne bouge plus, quoi quâil arrive. Nous le dĂ©gĂšlerons par code au moment du lancer.
Faites bien attention à faire ce réglage dans la scÚne
ball.tscn et pas dans la scĂšne world.tscn.
PlutĂŽt que de tester directement un bouton de la souris dans le code,
Godot propose un systĂšme dâactions : un nom (par
exemple aim) auquel on associe une ou plusieurs touches ou
boutons.
aim.+ Ă droite de lâaction).Les actions rendent le code indĂ©pendant du pĂ©riphĂ©rique : si on veut plus tard viser avec une autre touche, il suffit de changer lâassociation ici, sans toucher au script.
Nous allons afficher une ligne pour visualiser lâimpulsion qui sera appliquĂ©e Ă la balle.
Node2D en enfant de la balle, que vous
nommerez Aim.Line2D en enfant de
Aim.points. Leur position nâa
pas dâimportance, on va la gĂ©rer dans le code.Ajoutez un script au noeud Aim. Il doit rĂ©aliser les
choses suivantes :
Line2D
et le RigidBody2D de la balle, avec @export
(comme dans lâexercice prĂ©cĂ©dent), puis les assigner dans
lâinspecteur._process :
aim est maintenue (Input.is_action_pressed,
propriété visible).set_point_position de Line2D, et
get_local_mouse_position).Input.is_action_pressed renvoie true
Ă chaque frame tant que lâaction est maintenue.
Lancez le jeu : en maintenant le clic, la ligne doit relier la balle Ă la souris.
DerniÚre étape : quand on relùche le clic, la balle doit partir.
aim avec
Input.is_action_just_released, dans
_process.throw() que vous créez.throw() :
freeze).apply_central_impulse. La direction et la force
correspondent au vecteur qui va de la balle jusquâĂ la souris.Pour obtenir le vecteur qui va dâun point A Ă un point B, on calcule B - A.
Contrairement Ă is_action_pressed,
Input.is_action_just_released ne renvoie true
quâune seule fois, Ă la frame oĂč lâon relĂąche le
bouton. Câest exactement ce quâil nous faut pour dĂ©clencher un lancer
unique.
Une impulsion est un « coup » appliquĂ© en une fois, alors quâune force sâapplique de façon continue. Pour lancer un objet, on utilise donc une impulsion.
Pour aller plus loin, essayez dâajuster la puissance
du lancer, par exemple avec une variable @export qui
multiplie lâimpulsion.
Vous avez maintenant tous les ingrĂ©dients : des plateformes statiques, des plateformes tournantes rĂ©glables, et une balle que lâon peut lancer Ă la souris.
Ă vous de les assembler pour construire votre propre niveau !
CrĂ©ez un niveau oĂč la balle, lancĂ©e depuis un point de dĂ©part, doit rejoindre une zone dâarrivĂ©e.
Pour le moment, lâarrivĂ©e est purement visuelle. Nous verrons plus tard comment dĂ©tecter ça automatiquement.
Pour dupliquer une plateforme déjà placée,
sĂ©lectionnez-la dans lâarbre de la scĂšne et utilisez
Ctrl + D. Pensez Ă ajuster ensuite sa position, et sa
vitesse si câest une plateforme tournante.
Pour garder une scĂšne lisible, regroupez vos
éléments sous des noeuds Node2D bien nommés (par exemple
Platforms). Un arbre organisĂ© est beaucoup plus simple Ă
parcourir quand le niveau grandit.
R recommence le niveau.
reset dans
lâInput Map et associez-lui la touche
R.Input.is_action_just_pressed.get_tree().reload_current_scene().PhysicsMaterial avec une valeur de
Bounce Ă©levĂ©e, et observez lâeffet sur la balle.