Ce second TP portera sur la création d'un jeu de plateforme à l'aide de la bibliothèque de création de jeu Phaser.
Nous en profiterons pour approfondir notre connaissance de la bibliothèque, notamment en découvrant la gestion des images et en explorant la communication entre les scènes et différents types de collision.
Les notes des TP seront obtenues à partir de vos dépôts Git, vous devrez donc prendre grand soin de la qualité de ces dépôts et de leurs « commits ».
De manière similaire, les descriptions de vos « commits » devront être claires et informatives, afin de permettre l'évaluation de la progression de votre travail.
Vous avez vu dans le TP précédent comment mettre en place et configurer votre projet à la main. Il s'agit d'une tache fastidieuse, mais qui vous a permis de comprendre les différents éléments qui composent un projet JavaScript moderne.
Certains outils, à l'instar de EsLint permettent, au travers d'outils en ligne de commandes, de simplifier l'installation et la configuration. Mais la grande liberté qui vous est offerte dans le choix des outils ne vous permet pas d'avoir de solution clé en main pour installer et configurer directement tous les outils souhaités.
Une solution couramment employée est l'utilisation d'un dépôt Git contenant le squelette d'un projet que vous pouvez utiliser comme base de travail. L'utilisation de degit vous permet même de ne pas récupérer le dépôt Git et de démarrer à neuf. Cependant, cette solution vous impose de maintenir votre dépôt à jour.
Pour faire simple, nous allons juste reprendre les fichiers nécessaires depuis votre précédent projet. Dans un nouveau répertoire « r301-js-platformer », vous recopierez les fichiers suivant depuis votre projet précédent :
Vous modifierez le fichier « package.json » pour qu'il soit cohérent avec votre projet (nom, déscription...). Vous nettoierez le fichier « src/index.js » pour qu'il se contente de créer une instance de jeu avec la configuration de « src/config.js ».
Dans notre cas, il est peu probable que les outils et bibliothèque que vous utilisez soient obsolètes, mais si nécessaire, vous pouvez le faire à l'aide de la commande suivante :
npx npm-check-updates
Il s'agit d'un outil JavaScript, qui contrôle les dépendances de votre projet et vous indique leur version actuelle. Le cas échéant, vous pouvez mettre à jour toutes ou une partie des dépendances à l'aide de npm-check-updates ou de npm directement.
Une fois que les dépendances du projet sont installées, vous devriez être capable de visualiser une zone de jeu dans votre page web de développement. Aprés avoir validé votre projet avec EsLint, vous créerez un dépôt Git local dans lequel vous ajouterez une capture de l'état de votre projet.
Pour finir, vous répliquer le dépôt local sur le serveur distant GitLab du département sous le nom « r301-js-platformer » et vous vous assurerez que votre intervenant de TP y ait accès avec un rôle de « Reporter ».
Dans le TP précédent, tout le jeu se déroulait dans un même espace. Cependant, la plupart des jeux disposent de plusieurs écrans d'affichage, a minima un écran d'accueil et un écran de jeu.
Sur ce principe, vous allez créer une première scène Title
correspondant à l'écran d'accueil. Elle affichera le titre de votre jeu et une invite à cliquer ou presser une touche.
Afin de donner un peu de vie à votre page de titre et pour vous rappeler son fonctionnement, vous ajouterez un tween permettant d'animer la taille de la police de l'invite de jeu, avec une fonction d'interpolation élastique par exemple.
Vous créerez ensuite une deuxième scène Level1
représentant le premier niveau du jeu. Elle ne comportera pour l'instant qu'un texte l'identifiant.
Phaser permet de gérer plusieurs scènes actives en même temps, mais dans un souci de simplicité, nous ne gérerons qu'une scène à la fois. Vous prendrez donc soin lors de l'ajout de ces scènes à l'instance de jeu, de n'activer que la scène d'accueil.
Enfin vous ajouterez deux gestionnaires d'événements, l'un réagissant au clic de la souris et l'autre à l'appui d'une touche. Ils déclencheront tous les deux le démarrage de la scène Level1
.
Title
.
Level1
.
Pour créer le premier niveau du jeu, nous allons utiliser des images. Pour commencer, vous allez ajouter une image à votre projet permettant de représenter un bloc de plateforme solide. Afin d'être utilisé dans le jeu, une image doit être accessible par celui-ci. Vous placerez donc l'image suivante : « stone.png » dans le sous-répertoire « public/img ».
Le répertoire « public » est le répertoire que vite utilise pour fournir les ressources statiques du site (les « assets »). Les ressources statiques sont les ressources que vite n'a pas besoin de transformer, les images, sons, vidéos...
Vous ajouterez trois blocs de pierre à votre jeu à l'aide de l'usine à object du jeu. Un niveau de jeu se composant de très nombreux blocs de plateforme, la création et la gestion de chaque bloc individuellement va être rapidement fastidieux. La gestion collective, pour la collision par exemple, peut être rapidement résolu à l'aide des groupes, mais pour résoudre le problème de création de bloc individuellement, vous allez créer deux nouvelles classes : TileGroup
et StoneGroup
.
TileGroup
et StoneGroup
diagrammesConformément au diagramme précédent, la classe TileGroup
hérite de la classe Phaser.Physics.Arcade.StaticGroup
. Elle permet de créer des groupes d'images pavant la zone de jeu.
La propriété tileName
contiendra l'identifiant de l'image à utiliser. Les propriétés tileWidth
et tileHeight
représente la largeur d'une colonne et la hauteur d'une ligne du pavage produit par le groupe.
La méthode addTiles
crée et ajoute au groupe un ensemble de blocs d'image en une fois. les blocs d'images seront structurés sous forme d'un rectangle, x
et y
seront les coordonnées de la première image en haut à gauche avec width
et height
le nombre de blocs d'image en largeur et en hauteur. Pour simplifier la conception du niveau, les coordonnées seront exprimées en lignes et colonnes de blocs d'image, par exemple, dans notre cas l'image « stone.png » faisant 64×64, l'invocation de la méthode addTiles(2, 3, 3)
créera une plateforme de 3 blocs dont les coordonnées du coin supérieur gauche seront (128, 192) (2×64, 3×64). Encore une fois, afin de simplifier, le positionnement des éléments, vous configurerez l'origine de chaque bloc d'image créé dans le coin supérieur gauche.
Pour faciliter la création des groupes de blocs, vous permettrez l'utilisation fluide de la méthode addTiles
en retournant l'instance courante.
Vous pourrez alors créer la classe StoneGroup
conformément au diagramme précédent, et dont la fonction sera de produire un groupe spécialisé pour l'affichage de blocs de pierre. La méthode de classe preload
devra être invoquée depuis la méthode preload
d'une instance de scène pour réaliser le chargement de l'image.
Vous devriez maintenant être capable d'afficher plus facilement des groupes de pierre dans le niveau. Mais avant de poursuivre, penchons nous sur un dernier détail. Les plus attentifs auront remarqué que le groupe dont hérite TileGroup
provient de l'espace de nom du moteur physique Arcade. Les blocs d'image créés ont donc déjà un corps physique, pour les visualisés, vous pouvez activer le débogage dans la configuration du moteur physique, lors de la configuration du jeu.
Vous devez probablement constater un décalage entre les images et la boîte englobante de leur corps physiques. Ceci est dû au fait que vous avait modifié l'origine des images après leur création et que Phaser ne met pas à jour les corps physiques. Pour résoudre ce problème, vous devez rafraîchir le corps physique des blocs d'image.
TileGroup
et StoneGroup
.
Maintenant que le groupe de blocs de pierre est fonctionnel, de manière similaire, vous créerez un groupe de blocs de lave : LavaGroup
, utilisant l'image « lava.png ».
Vous pourrez enfin créer le premier niveau du jeu afin qu'il corresponde au schéma suivant :
LavaGroup
.
Comme précédemment, vous commencerez par ajouter l'image du joueur à votre projet « player.png »
Vous allez créer la classe Player
et l'employer dans la classe Level1
conformément au diagramme suivant :
Player
diagrammeVous commencerez par créer la classe Player
avec uniquement sa propriété de classe, son constructeur et la méthode de classe preload
. L'image du joueur (player.png) est en réalité un dictionnaire d'image du joueur, chaque vignette faisant la même taille, 40×40. Pour charger ce type d'image, vous utiliserez la méthode spritesheet
. Pour la configuration des vignettes (frameConfig
), vous ne fournirez que la largeur et la hauteur. Dans le constructeur, vous prendrez soin de redéfinir l'origine de l'image en haut à gauche et d'ajouter au joueur un corps physique.
Une fois créée, vous utiliserez la classe pour ajouter un joueur dans à la case (1, 7) du premier niveau. Vous constaterez que le joueur reste suspendu en l'air, vous ajouterez donc une gravité de 1000. Et pour empêcher le joueur de traverser les plateformes de pierre, vous ajouterez un gestionnaire de collisions entre le joueur et le groupe des blocs de pierre.
Maintenant, le joueur devrait tomber au sol, et ne plus bouger. Vous allez remedier à celà en ajoutant un peu d'interaction. Vous commencerez par ajouter les méthodes #move
, moveRight
, moveLeft
et halt
à la classe Player
.
#move
permet de déplacer le joueur latéralement. vous utiliserez un tween permettant d'animer l'abscisse de la vélocité du corps physique. L'interpolation poura être cubique, de 0 à la valeur passée en paramètre sur une durée de 300ms.moveRight
et moveleft
utilise #move
pour animer l'abscisse de la vélocité du joueur à 300 et -300 respectivement.halt
permet d'arrêter le joueur en retournant l'abscisse de la vélocité du joueur à 0. Vous utiliserez un tween pour l'animation. L'interpolation pourra être cubique sur une durée de 300ms.Pour utiliser ces méthodes, vous ajouterez les méthodes #handleInput
et #handleMove
à la classe Level1
.
#handleInput
permet essentiellement de structurer le code. Elle a pour fonction de regrouper tous les gestionnaires d'événements d'interaction. Dans votre cas, vous enregistrerez des gestionnaires d'événements pour l'appui et la libération des touches gauche et droite, ces gestionnaires invoqueront la méthode #handleMove
lors de chaque événement.#handleMove
permet de gérer le mouvement latéral. Le joueur est arrêté si les deux touches sont pressées ou relachées. Le joueur se déplace à droite si la touche droite est pressée toute seule et à gauche si la touche gauche est pressée toute seule.Les animations fonctionnent bien, car les durées de mouvement et d'arrêt sont les mêmes. Cependant si l'une de ces valeurs est modifiées, vous pourrez constater des erreurs de fonctionnement. Pour pallier à ces erreurs, vous enregistrerez les tweens que vous créez dans une propriété d'instance et vous pourrez ainsi supprimer le précédent avant d'en créer un nouveau.
Pour finir, sur les mêmes bases, vous ajouterez la gestion du saut au joueur. Afin d'empêcher le joueur de s'envoler en appuyant plusieurs fois sur la touche de saut, vous contrôlerez que le joueur touche le sol avant de réaliser le saut.
Player
.
Vous avez dû remarquer que vous ne pouviez pas voir l'ensemble de la scène, pour résoudre ce problème, vous allez configurer la caméra afin qu'elle se déplace en suivant les déplacements du joueur. Dans la scène, vous activerez le suivi du joueur par la caméra principale du jeu, à l'aide de la méthode startFollow
.
Suite à cette modification, vous constaterez que la caméra étant centrée sur le joueur, l'affichage en bord de scène affiche une grande zone vide. Pour revenir à un comportement plus usuel, où le jeu n'affiche que la scène, vous allez limiter la zone accessible à la caméra. Vous commencerez par ajouter une méthode cachée #setBounds
à la scène qui recevra en paramètres les bornes de la scène, pour ce premier niveau, il s'agit d'une zone de 1472×640 (23*64 et 10*64) pixels dont le coin supérieur gauche est en (0,0). Et dans cette méthode, vous pourrez fixer les limites de déplacement de la caméra principale à l'aide de la méthode setBounds
.
Pour finir, vous noterez que le joueur peut sortir de la zone de jeu, ce qui n'est pas pratique pour le joueur. Dans son constructeur, vous allez limiter le déplacement du joueur aux dimensions du monde à l'aide de la méthode setCollideWorldBounds
. Vous devriez constater en vous déplaçant vers la gauche de la scène que le joueur est limité aux dimensions initiales de la zone de jeu. Vous mettrez donc à jour les dimensions du monde pour qu'il corresponde à la scène à l'aide de la méthode setbounds
dans la mèthode #setBounds
.
Le joueur devrait maintenant, expérimenté une expérience de jeu plus conventionnelle.
Vous devez vous souvenir que l'image que vous avez chargé pour le joueur était un dictionnaire d'images et que pour l'instant le joueur est un peu rigide lors de ces déplacements.
Dans la classe Joueur
, vous ajouterez une nouvelle méthode privée #createAnims
. Cette méthode nour permet surtout d'organiser le code en regroupant la création des animations en un même endroit, mais son invocation sera réalisée uniquement dans le constructeur.
Dans un premier temps, la méthode #createAnims
, ajoutera deux animations à notre joueur à l'aide de la méthode create
du gestionnaire d'animations du Joueur
:
Pour des exemples de création d'animations, vous pouvez vous référer à la documentation.
Vous pourrez ensuite utiliser ces animations lors du déplacement du joueur dans les méthodes moveRight
, moveLeft
et halt
. Pour le déplacement à gauche, vous utiliserez l'animation de gauche en retournant votre Sprite
à l'aide de sa méthode setFlipX
.
Dans cette section, vous allez ajouter un arrière-plan à votre scène. Cependant, pour l'instant, vous ne pouvez ajouter qu'une image recouvrant toute la surface de jeu ou créer et positionner vous-même plusieurs images afin qu'elles recouvrent la surface de jeu. Vous allez utiliser un nouveau type d'image permettant de paver automatiquement une surface.
Vous commencerez par ajouter à votre projet l'image employée recouvrir l'arrière-plan : « bg.png ».
Vous allez maintenant pouvoir ajouter une image de type TileSprite
à votre scène, afin qu'elle occupe toute la zone de jeu. Vous penserez à désactiver le défilement afin que cette image reste toujours à l'écran.
Nous avons maintenant un arrière-plan que nous avons pu remplir avec une toute petite image. Cependant, cette image ne bouge pas lorsque la caméra suit le joueur, ce qui n'est pas convenable dans de nombreux cas. Pour résoudre ce problème conformément à la documentation de la classe, vous utiliserez la méthode setTilePosition
conjointement aux propriétés scrollX
et scrollY
de la camera principale lors de l'événement « followupdate » de la caméra principale.
Vous avez maintenant, un arrière-plan fonctionnel, mais il est courant d'avoir plusieurs images pour l'arrière-plan. Afin de se simplifier la gestion, vous allez réorganiser votre code en créant une classe Background
héritant de la classe Phaser.Physics.Arcade.StaticGroup
. Dans un premier temps, comme précédemment, vous y déplacerez votre code concernant l'arrière-plan en le répartissant dans le constructeur et une méthode de classe preload
Une fois votre projet de nouveau fonctionnel, vous ajouterez les images « dust1.png » et « dust2.png » à votre projet.
Vous pourrez ensuite ajouter la variable suivante à votre module JavaScript contenant la classe Background
:
Vous pourrez parcourir ce tableau pour ajouter les images à votre arrière-plan. Vous utiliserez les urls comme clés des images chargées et en bouclant sur les clés du tableau, vous ajouterez les images à votre arrière-plan.
Dans notre cas, nous utilisons plusieurs images pour gommer un peu l'aspect répétitif de la texture de fond, vous allez donc décaler les images de manière similaire lors du déplacement de la caméra, mais sur le même principe, il serait facile de mettre en place un effet de défilement parallaxe en faisant varier le décalage de chaque image.
Background
.Pour illustrer la mort du joueur, vous allez utiliser un système de particules. Ceux-ci utilisent une image pour afficher les particules, vous commencerez par ajouter l'image « particle.png » à votre projet et vous ajouterez son chargement dans la classe Player
.
Vous pourrez ensuite ajouter une méthode death
au joueur qui provoquera la mort du joueur lors de son invocation.
Cette méthode commencera par créer un système de particules centré sur le joueur avec la configuration suivante :
Afin d'empêcher d'autre collision avec l'environnement, vous allez
Vous pourrez faire ensuite produire une explosion d'une vingtaine de particles et cacher le joueur.
Vous provoquerez le redémarrage de la scène à l'aide de la méthode restart
du gestionnaire de scène. Cependant, pour que l'animation de l'explosion soit visible, vous différerez le redémarrage de la scène ainsi que la réactualisation du clavier.
Pour finir, vous utiliserez cette méthode lors de la collision du joueur avec un bloc de lave. Vous devriez maintenant voir mourir votre joueur lorsqu'il tombe dans la lave et la scène devrait redémarrer.
Vous allez ajouter un ascenseur permettant de changer de scène. Pour cela, vous allez créer une classe Elevator
héritant de Phaser.Physics.Arcade.StaticGroup
. La classe proposera le chargement de la bibliothèque d'image « elevator.png », contenant des vignettes de 64×64, et le constructeur ajoutera au groupe un sprite que vous stockerez dans une propriété d'instance back
.
Vous devriez maintenant être capable d'afficher l'ascenseur dans la scène à la case (21, 7) de la scène.
Vous ajouterez une méthode privée #createAnims
que vous invoquerez dans le constructeur et qui créera les animations. Pour le moment, cette méthode créera une animation « open », comportant les vignettes de 0 à 3 à une vitesse de défilement de 20.
Vous allez maintenant pouvoir ajouter la méthode moveIn(player)
à la classe Elevator
permettant de faire rentrer le joueur dans l'ascenseur.
Vous commencerez par désactiver le clavier et invoquer la méthode halt
du joueur, puis vous provoquerez l'ouverture de l'ascenseur à l'aide de l'animation « open ».
Vous déplacerez ensuite le joueur au centre de l'ascenseur à l'aide d'un « tween ». Puis en différent l'invocation afin que l'animation soit finie, vous réactiverez le clavier et redémarrerez la scène.
Pour activer l'ascenseur, vous ajouterez un nouveau gestionnaire de touche de clavier pour l'interaction du joueur avec la touche bas. Le gestionnaire d'événement invoquera la méthode privée #handleInteract
que vous ajouterez à la scène du premier niveau. Cette méthode utilisera la méthode overlap
du moteur physique (this.physics.world
) pour tester si le joueur est sur l'ascenseur en même temps qu'il est au sol et dans ce cas, invoquera la méthode moveIn
.
Elevator
.L'animation est fonctionnelle, mais pour refermer les porte de l'ascenseur, il faudrait les afficher devant le joueur. Il serait possible de jouer avec l'indice de profondeur (z-index), mais cette solution demande un peu de rigueur pour être cohérente dans le temps. Une autre solution consiste à créer des calques afin de gérer plusieurs niveaux de profondeur.
Mais avant d'ajouter des calques à votre projet, vous allez réorganiser votre code afin de simplifier la création des niveaux. Vous commencerez par créer une classe Level
héritant de la classe Phaser.Scene
. Cette classe va comporter ce qui concerne le joueur, la caméra et l'interaction du joueur. Elle contiendra :
preload
qui chargera les images du joueur.Level1
(#handleInput
, #handleMove
, #handleJump
, #handleInteract
et #setBounds(levelBound)
).initScene(xPlayer, yPlayer, levelBound)
qui créera le joueur à la position (xPlayer, yPlayer) et initialisera la caméra pour suivre le joueur. Elle invoquera aussi les méthodes #handleInput
et #setBounds(levelBound)
.De plus, la méthode #handleInteract
impose que vous ayez accès à l'ascenseur de la scène. Cependant, pour plus de généricité, vous ajouterez une propriété elevators
à la classe Level
qui contiendra un tableau vide par défaut. C'est cette propriété qui contiendra les ascenseurs de la scène, que vous testerez dans la méthode #handleInteract
.
Vous ferez ensuite hériter la classe Level1
de la classe Level
. Vous penserez à invoquer la méthode preload
du parent dans sa méthode preload
et la méthode initScene
dans sa méthode create
. Vous penserez à ajouter l'ascenseur au tableau d'ascenseur de Level
.
Vous devriez avoir de nouveau un projet fonctionnel, à l'exception près, qu'en fonction de la position de l'invocation de la méthode initScene
, le joueur peut être créé derrière l'arrière-plan.
Pour résoudre ce problème, vous allez ajouter un ensemble de calques à votre classe Level
:
Vous ajouterez le joueur au calque « player ».
Dans la classe Level1
, vous ajouterez les différents éléments du jeu dans leur calque. Background
ira dans le calque « bg » et tout le reste dans le calque « back ».
Pour les groupes, vous ne pouvez pas directement les ajouter au calque, vous devez ajouter le tableau de ces éléments : .children.entries
.
Pour l'ascenseur, vous ajouterez dans le calque « back directement l'image de fond de l'ascenseur (back
).
Level
.Level1
pour hériter de Level
.Level
.Maintenant que vous votre scène est organisée en calque, dans le constructeur de la classe Elevator
vous allez pouvoir ajouter un sprite qui sera affiché devant le joueur. Vous le stoquerez dans une propriété d'instance front.
Dans la scène, vous pourrez accéder aux propriétés front et back de l'ascenseur pour ajouter les sprites aux calques correspondants.
Enfin, vous créerez une nouvelle animation « open » pour ce nouveau sprite, réalisant l'animation des vignettes 4 à 7 de la bibliothèque d'images.
Puis, dans la méthode moveIn
, lors de la réalisation du déplacement du joueur au centre de l'ascenseur onComplete, vous pourrez jouer l'animation de fermeture des portes à l'aide de la méthode playReverse
.
Maintenant que l'animation fonctionne correctement, vous allez pouvoir provoquer le changement de scène. Dans ce but, le constructeur de la classe Elevator
recevra un nouveau paramètre contenant la clé de la scène vers laquelle emmène l'ascenseur. Ce paramètre sera sauvegarder dans une propriété d'instance to
, pour pouvoir être utilisée dans la méthode moveIn
à la fin des animations pour démarrer la nouvelle scène plutôt que de redémarrer la scène actuelle.
Pour que votre ascenseur soit fonctionnel, vous créerez une classe Level2
représentant votre deuxième niveau. Pour l'instant celui-ci se conformera au schèma suivant :
Aprés avoir ajouté la scène au jeu, vous ajouterez la destination de l'ascenseur du niveau 1 afin qu'il emmène au niveau 2.
Maintenant, votre joueur doit parvenir à passer du niveau 1 au niveau 2. Cependant, l'animation est un peu décevante. Afin d'y remédier, vous allez transmettre l'information de la provenance du joueur lors du démarrage de la scène. Dans la méthode moveIn
de la classe Elevator
, vous passerez en deuxième paramètre de la méthode start
un object JavaScript comportant une propriété from
avec comme valeur la clé de scène comportant l'ascenseur. Cet objet JavaScript sera transmis, lors du démarrage de scène, en paramètre de la méthode créate
de la scène démarrée. Vous pourrez remplir (set
) les données de la scène avec celui-ci.
Vous ajouterez ensuite une méthode moveOut(player)
à la classe Elevator
permettant de faire sortir le joueur de l'ascenseur.
Vous commencerez par désactiver le clavier et invoquer la méthode halt
du joueur, placer le joueur au centre de l'ascenseur. Vous afficherez, à l'aide de la méthode setTexture
, le sprite arrière comme ouvert (vignette 3) et le sprite avant comme fermé (vignette 4).
Vous allez provoquer l'ouverture de l'ascenseur à l'aide de l'animation « open » sur le sprite avant, mais avant, vous allez enregistrer un gestionnaire d'événement unique réagissant à la fin de l'animation du sprite avant ("animationcomplete"
). Dans la fonction de rappel, vous réactiverez la gestion du clavier et vous provoquerez la fermeture du sprite arrière.
Pour finir, lors de la création des scènes, vous pourrez déclencher la sortie de l'ascenseur en fonction de la provenance de l'utilisateur que vous obtiendrez à l'aide de la méthode get
du gestionnaire de données de la scène.
moveOut(player)
à la classe Elevator
.Une fois les transitions entre les scènes opérationnelles, vous allez pouvoir créer le deuxième niveau. Dans ce niveau, vous allez mettre en place un nouveau type de blocs, les échelles.
Vous commencerez donc par ajouter une nouvelle image à votre projet : « ladder.png ». Il s'agit de l'image d'un bloc d'échelle.
Comme précédemment, vous créerez une classe LadderGroup
pour ajouter des ensembles de blocs à votre scène. Cependant, les plus attentifs constateront que l'image étant de dimensions 40×64, le positionnement des images ne va pas être correct. Pour palier à ce problème, vous ajouterez deux paramètres (offsetX
et offsetY
) avec une valeur par défaut de 0 au constructeur de TileGroup
. Vous initialiserez des propriétés d'instance pour conserver ces valeurs et vous les utiliserez dans la méthode d'instance addTiles
pour pouvoir décaler la position de chaque image lors de la création par lot. Cette modification ne devrait pas avoir d'impact sur votre projet. Vous pourrez ensuite créer la classe LadderGroup
pour afficher des groupes d'échelles algnés sur les cases de dimensions 64×64.
Vous pouvez maintenant mettre à jour votre classe Level2
pour que le deuxième niveau corresponde au schèma suivant :
En vous inspirant de la scène Title
, vous ajouterez une nouvelle scène à votre jeu indiquant que le jeu est fini, vous penserez à l'ajouter à votre instance de jeu.
LadderGroup
pour gérer les groupes d'échelles.Pour pouvoir monter ou déscendre des échelles, vous ajouterez la gestion des touches haut et bas. Les touches haut et bas peuvent déjà être affectées, mais ici, nous parlons de l'action du joueur, de monter ou descendre. Le fait de décorréler l'action du joueur des touches dans votre code vous offre la souplesse de pouvoir changer d'avis sur les touches associées aux actions, voir de laisser votre joueur les configurer.
Ensuite, vous commencerez par ajouter trois méthodes d'instance : climbUp(ladders)
, climbDown(ladders)
et climbStop
à la classe Player
. Puis, vous ajouterez la gestion des événements pour l'activation et la libération des touches associées à la montée et à la descente. Ils ne seront effectifs que lorsque le joueur est en contact avec une des échelles, vous utiliserez la méthode overlape
pour tester la superposition des objets. Dans le cas où il y a superposition :
Dans la classe Player
, pour les méthodes climbUp(ladders)
et climbDown(ladders)
, le paramètre ladder
correspond au groupe d'échelles avec lesquelles interagit le joueur. À l'exception de la direction, dans ces méthodes, vous devez :
setAllowGravity
).stop
).Dans la méthode climbStop
, si un groupe d'échelles est mémorisé, vous animerez un retour à 0 de la vitesse en y du joueur à l'aide d'un tween, sur 50ms par exemple.
Vous devriez maintenant pouvoir monter et descendre aux échelles, mais le jeu ne réalise pas lorsque vous les quittées. Pour résoudre ce problème, vous ajouterez une méthode preUpdate
à la classe Player
pour vérifier si le joueur quitte l'échelle sur laquelle il se trouve. Si un groupe d'échelles est mémorisé, vous testerez si le joueur est toujours dessus à l'aide de la méthode overlape
et sinon, vous réactiverez la gravité pour le joueur et vous oublierez le groupe d'échelles.