Dans ce tuoriel, nous voyons comment placer des ennemis sur une carte générée par Tiled. Nous voyons également un premier modèle de mobilité simple, visant à faire se déplacer ces ennemis cette carte selon des mouvements simple d’aller-retours.
Démo du résultat à obtenir avec ce tutoriel
Démo à faire :
Base de départ pour ce tutoriel
On considère un jeu existant avec une carte déjà créée sur Tiled et chargée. Par exemple le résultat du tutoriel Créer une carte sur Tiled et l’intégrer en Phaser 3.
I - Ajouter des ennemis en nombre à notre jeu
Pour ajouter un ennemi simple dont on aurait déjà la texture, il nous suffit d’ajouter ce dernier avec l’instruction this.physics.add.sprite(…) en précisant en paramètres les coordonnées de l’ennemi.
Or ce code implique d’avoir autant de lignes que d’ennemis à créer, ce qui peut vite donner un programme interminable. Une solution simple consiste à positionner des points d’apparitions (spawn point) sur une carte Tiled, puis à récupérer les coordonnées de ces points dans le code Phaser, et pour chacun de ces points – donc via une boucle- créer un ennemi à l’endroit indiqué.
I.1 Ajout des points d'apparition des ennemis sur la carte
- Dans tiled, sur une carte existant, ajoutez un nouveau calque d’objet (et non de tuiles), en anglais Object Layer. Le calque se distingue par un icône différent des autres constitué de polygones. Donnez un nom à ce calque, par exemple calque_ennemis (ce nom sera réutilisé dans la suite du code, il sera à adapter s vous le modifiez)
- Sur ce calque, on va placer des points. Sélectionnez ce calque, vous notez que la barre des outils change, et que les outils objets sont désormais accessibles. Sélectionnez l’outil point et placer un premier point sur la carte.
Quand un point apparait et est sélectionné, ses propriétés sont affichées par défaut sur la fenêtre de gauche, comme présenté sur la figure ci-dessous :
Cette fenêtre est très importante : elle présente les coordonnées du point (dans l’exemple 257, 292), mais permet également de mettre un nom sur l’objet. Ici nous avons mis le nom à ‘ennemi« . Avoir un nom permet de positionner des objets de différents types (ennemis, item, etc), et de les distinguer par la suite dans le code.
Notez également un élément non exploité ici et pourtant essentiel : l’ajout de propriétés. On peut ajouter les propriétés de notre choix et les récupérer par la suite dans le code. On pourrait par exemple imaginer une propriété pointsDeVies et affecter directement les points de vie pour chaque ennemi dans la carte, avec des valeurs spécifiques par objets.
- En utilisant la fenêtre de propriété du point, donnez un nom à votre point, appelez le « ennemi« . Votre point se présente désormais de la façon suivante sur le calque.
- Réitérez l’opération plusieurs fois en ajoutant plusieurs points et en leur appliquant le même nom ennemi à chaque fois, ou en copiant le point créé à différents endroits.
- Votre carte est prête. Sauvegardez, exportez enfin cette dernière dans un fichier au format json et transférez la sur Phaser.
I.2 Création des ennemis à partir des points d'apparition de la carte
L »étape suivante consiste à charger le calque d’objets, puis à extraire l’ensemble des points de ce calque avec la méthode getObjectLayer() , et à les stocker dans un tableau – nommé tab_points dans l’exemple ci-dessous – . Pour chacun des points extraits :
- on regarde son nom.
- Si son nom est égal à « ennemi », on va créer un sprite sur les coordonnées du point.
- On va ajouter ce point à un groupe d’ennemis qu’on aura créé précédemment.
La syntaxe générale de cet algorithme est présentée dans le morceau de code ci-dessous :
// extraction des poitns depuis le calque calque_ennemis, stockage dans tab_points
const tab_points = carte.getObjectLayer("calque_ennemis");
// on fait une boucle foreach, qui parcours chaque élements du tableau tab_points
tab_points.objects.forEach(point => {
if (point.name == "ennemi") {
var nouvel_ennemi = this.physics.add.sprite(point.x, point.y, "img_ennemi");
groupe_ennemis.add(nouvel_ennemi);
}
});
Comme l’identifiant recommencerNiveau n’est plus vraiment utile puisque la fonction est directement présente, on peut même le supprimer, et écrire simplement :
II - Ajouter un modèle de mobilité à nos ennemis
II.1 initialisation de la mobilité (partie create)
/*****************************************************
* ajout du modele de mobilite des ennemis *
******************************************************/
// par défaut, on va a gauche en utilisant la meme animation que le personnage
groupe_ennemis.children.iterate(function iterateur(un_ennemi) {
un_ennemi.setVelocityX(-40);
un_ennemi.direction = "gauche";
un_ennemi.play("anim_tourne_gauche", true);
});
II.2 mise a jour en temps réel (partie update)
groupe_ennemis.children.iterate(function iterateur(un_ennemi) {
if (un_ennemi.direction == "gauche" && un_ennemi.body.blocked.down) {
var coords = un_ennemi.getBottomLeft();
var tuileSuivante = calque_plateformes.getTileAtWorldXY(
coords.x,
coords.y + 10
);
if (tuileSuivante == null || un_ennemi.body.blocked.left) {
// on risque de marcher dans le vide, on tourne
un_ennemi.direction = "droite";
un_ennemi.setVelocityX(40);
un_ennemi.play("anim_tourne_droite", true);
}
} else if (un_ennemi.direction == "droite" && un_ennemi.body.blocked.down) {
var coords = un_ennemi.getBottomRight();
var tuileSuivante = calque_plateformes.getTileAtWorldXY(
coords.x,
coords.y + 10
);
if (tuileSuivante == null || un_ennemi.body.blocked.right) {
// on risque de marcher dans le vide, on tourne
un_ennemi.direction = "gauche";
un_ennemi.setVelocityX(-40);
un_ennemi.play("anim_tourne_gauche", true);
}
}
});