❤ 1Gari
Premier contact, partie 2 :
Créer des ennemis et les faire interagir avec le joueur
Dans ce second tutoriel, nous allons créer les ennemis et voir comment les faire interagir avec le joueur dans une scène qui incorpore les deux.
Retrouvez la première partie ici.
Pour cette série de tutoriels, j’ai décidé de vous proposer quelque chose de simple : notre joueur doit esquiver les ennemis qui tombent du haut de l’écran.
Organisation de la scène « Enemy »
Notre scène va être composée des mêmes éléments que notre Player, c’est-à-dire :
Area2D
|-Sprite
|-CollisionShape2D
Nous allons encore une fois utiliser l’icône de Godot pour lui donner une texture. Cependant, afin de ne pas le confondre avec le personnage jouable, nous allons utiliser la fonction modulate dans l’inspecteur.
Cette fonction permet d’appliquer une couleur sur une texture, mettons du rouge pour notre ennemi.
Script
Créez un script sur le nœud Enemy.
La première chose que nous allons faire est de récupérer la largeur de la fenêtre pour faire apparaître les ennemis aléatoirement le long de celle-ci.
En haut du script, écrivez cette ligne :
1
| onready var screenSize = get_viewport_rect().size |
onready va permettre d’initialiser la variable pendant l’execution de ready().
Avec screenSize, on récupère la taille de la fenêtre sous forme d’un Vector2D(). Un viewport est une vue dans l’écran, sur des projets plus compliqués il peut y en avoir plusieurs, par exemple pour avoir plusieurs caméras, certains shaders, etc... Ici nous n’avons qu’un seul viewport, celui de base, qui prend toute la fenêtre de notre jeu.
Dans la fonction _ready() ajoutez le code suivant :
1
2
| var spawnPosition = randi() % int(screenSize.x) + 30
position = Vector2(spawnPosition,0) |
randi()% N + X permet de prendre une valeur au hasard dans l’intervalle [0, N-1].
Le « + X » et optionnel, s’il est défini, l’intervalle sera [X, N-1].
Ici on enlève 30 de chaque côté de l’intervalle par rapport à la largeur de la fenêtre pour éviter que les ennemis apparaissent tout au bord.
position donne la position du nœud.
Maintenant que notre ennemi apparaît, faisons-le descendre l’écran.
En haut du script, ajoutez :
Dans la fonction _process(), écrivez ceci :
1
| position.y += speed*delta |
Ici nous n’agissons que sur l’axe Y en faisant descendre notre ennemi à la verticale.
Problème : l’ennemi continuera à descendre après avoir quitté l’écran ! Détruisons-le si c’est le cas.
Toujours dans _process() :
1
2
| if position.y > screenSize.y + 30:
queue_free() |
queue_free() va supprimer le nœud à la fin de la frame. En supprimant le nœud, on supprime tous les nœuds enfants.
Testez, notre ennemi tombe jusqu’en bas de l’écran !
Nous avons besoin de faire se rencontrer nos ennemis et notre joueur. Créons une nouvelle scène (Scène > Nouvelle Scène), choisissez Noeud2D. Renommez la Game.
Cliquez sur la chaîne en haut de l’arbre (image ci-dessous)
Sélectionnez le Player, et Ouvrir.
Nous avons créé une instance de notre joueur dans notre scène Game.
Sauvegardez la scène.
Avant de continuer, dans la barre d’outils en haut de l’écran, cliquez sur Projet >Paramètres du projet ; allez dans Application > Run. Changez la Main Scene, actuellement Player.tscn par Game.tcsn. Cela permettra de lancer cette scène par défaut.
Revenons sur la scène. Pressez F5. Notre joueur se déplace convenablement dans notre scène Game.
Ajoutons des ennemis.
Nous allons le faire via un script, pour ajouter un ennemi à la fin d’un timer. Commençons par le timer : ajoutez un nœud enfant à Game, et cherchez Timer, ajoutez-le. Renommez-le SpawnTimer. Dans l’inspecteur, réglez le wait time à 0.2.
Ajoutez un script à Game.
Il faut faire apparaître un ennemi quand le timer est fini.
Cela va faire appel à un concept essentiel de Godot : les Signaux.
Les signaux permettent d’envoyer un message à un nœud lorsqu’une action se produit, par exemple quand notre joueur et notre ennemi vont rentrer en collision, quand un bouton est pressé ou encore quand un timer finit. Les nœuds possèdent leur propre liste de signaux disponibles mais il est aussi possible de définir des signaux personnalisés.
Pour se faire, cliquez sur le nœud Timer et regardez du côté de l’inspecteur (à droite), il y a un onglet « Nœud ». Cliquez dessus pour voir les signaux :
Faites un clic droit sur timeout(). Sélectionnez le nœud Game et cliquez sur Connecter.
Deux lignes sont apparues dans le script.
La petite flèche verte à gauche de la ligne func _on_Timer_timeout(): nous dit que cette fonction est connectée à un signal. Cette fonction sera appelée dès que le timer finira.
Dans la fonction _ready(), ajoutez la ligne :
$nomDuNoeud permet d’accéder au nœud dans l’arbre.
start() lance le timer.
Au dessus du _ready(), ajoutez la ligne :
1
| onready var enemyScene = preload("res://Enemy.tscn") |
Nous chargeons dans enemyScene la packedScene Enemy, cela va nous permettre de l’instancier.
Pour ce faire allez dans la fontion _on_Timer_timeout(), supprimez pass et ajoutez :
1
2
| var enemy = enemyScene.instance()
add_child(enemy) |
La variable enemy est une instance de notre scène Enemy.
add_child ajoute cette instance au nœud à la scène Game.
Testez, une pluie d’ennemis tombe sur notre joueur !
Nous allons maintenant gérer la collision entre notre ennemi et notre joueur.
Nous allons à nouveau utiliser un signal : area_entered().
Pour se faire, cliquez sur le nœud Enemy et regardez du côté de l’inspecteur (à droite), il y a un onglet « Nœud ». Cliquez dessus pour voir les signaux. Faites un clic droit sur : area_entered(area : Area2D). Cliquez sur Connecter, normalement le nœud Enemy est déjà sélectionné (c’est de toute façon le seul nœud de la scène avec un script !), et validez.
Le « area » entre parenthèse est un argument de la fonction, elle permet de récupérer l’area qui rentre dans l’area de notre ennemi.
Supprimez la ligne avec pass et ajoutez les lignes :
1
2
| if area.name == "Player":
get_tree().quit() |
Une simple condition, si le nom de l’area est « Player », on quitte le jeu.
Les scripts doivent ressembler à ceci :
L'Enemy :
Le Game :
Testez, cela doit fonctionner.
Vous y êtes arrivé !
|