Si vous n'avez jamais joué au célèbre jeu du Serpent , levez la main !
Je dis cela, mais je suppose qu'aujourd'hui, la nouvelle génération n'a peut-être jamais entendu parler de ce jeu, qui peut paraître un peu démodé étant donné les possibilités offertes par les ordinateurs d'aujourd'hui et le Web.
Et pourtant, il fut un temps où le jeu Snake était un jeu auquel tous les propriétaires de téléphones portables passaient énormément de temps à jouer. Oui, à l’époque, on ne parlait pas de smartphones, juste de téléphones.
C'était la bonne époque, comme dit le proverbe, et Nokia a popularisé le jeu à travers ses appareils mobiles, qui étaient aussi une référence. Aujourd'hui, il ne reste plus grand-chose de la domination de Nokia sur le monde mobile et sur le jeu Snake.
Pour ceux qui sont nostalgiques de ce jeu – et j'en fais partie, je dois l'avouer – ce tutoriel vous apprendra comment le recréer pour le Web. Pour ce faire, j'utiliserai l'API Canvas et JavaScript de HTML5.
C'est aussi l'occasion d'apprendre à utiliser les classes en Javascript et à créer une boucle de jeu efficace pour les jeux Web.
Pour commencer, nous allons créer la page Web qui nous permettra de jouer au jeu Snake que nous allons développer dans ce tutoriel. Vous verrez bientôt que cette page Web ne présente aucune difficulté. Deux divs, un pour le titre de la page et un autre pour afficher la zone où le serpent va se déplacer.
A cela, je vais ajouter un peu de CSS pour centrer ces divs en leur appliquant une largeur fixe :
Comme je l'ai expliqué en introduction de ce tutoriel, je vais utiliser une classe Snake dédiée pour modéliser le jeu. Cela vous permettra également de découvrir comment manipuler les classes en JavaScript.
Notre Serpent aura les propriétés suivantes :
A la fin du constructeur, une méthode init est appelée pour initialiser le serpent au début de la partie. Lorsqu'un nouveau jeu doit être démarré, appelez simplement à nouveau cette méthode init.
Cela nous donne le code suivant pour notre classe Snake :
Dans la méthode init, vous pouvez définir d'autres propriétés du serpent, comme un pointeur vers sa tête et un pointeur vers sa queue. Le tableau elements stockera tous les éléments du serpent à un instant donné. La propriété points est utilisée pour stocker des points pour le jeu en cours, tandis que la propriété level est utilisée pour définir le nombre de points accumulés pour augmenter les fps du jeu. Plus le nombre de fps est élevé, plus le serpent se déplacera rapidement.
Puisque la propriété fps représente le nombre d'images par seconde, nous devons avoir une propriété fpsinterval évaluée au résultat de la division de 1 seconde (ou 1 000 millisecondes) par le nombre d'images par seconde souhaité.
Le principe du jeu Snake est simple : vous devez guider le serpent à l'aide des quatre flèches directionnelles pour qu'il mange le maximum de pommes qui apparaissent sur le plateau. Chaque fois que vous mangez une pomme, le serpent grandit d’un élément. À mesure que le serpent grandit, il vous sera difficile d’éviter de toucher sa propre queue. Si vous ne le faites pas, vous perdrez et le score repartira de zéro. Bien sûr, chaque fois que vous mangez une pomme, vous marquez un point.
Il convient de souligner que la version de Snake que nous allons implémenter est celle où toucher les bords du tableau ne vous fait pas perdre. Cela vous fait simplement basculer du côté opposé. Les deuxièmes versions du jeu Snake ont été implémentées de cette manière par Nokia.
Puisque le serpent doit manger une pomme, il faut afficher cette pomme sur le plateau de manière aléatoire, en prenant soin de ne pas générer de pomme directement sur un élément du serpent.
Cela nous donne la méthode generatefood suivante pour notre classe Snake :
Notre classe Snake progresse et nous devons maintenant créer une méthode pour rendre le serpent à l'écran. Il faudra également afficher le nombre de points du joueur à un instant donné et enfin afficher la pomme à manger. La position de la pomme est stockée dans la propriété alimentaire de la classe Snake.
Pour afficher le serpent à l'écran, j'utilise l'API Canvas de HTML5.
Je vais utiliser les primitives de dessin de cette API pour dessiner des rectangles représentant les différents éléments du serpent ainsi que la pomme à manger. Je vais appliquer une couleur différente à la pomme et au serpent afin que le joueur puisse les distinguer.
Cela donne le code suivant pour la méthode draw de notre classe Snake :
Nous avons maintenant un serpent que nous pouvons afficher à l'écran. Tout cela est très bien, mais nous devons ajouter un support au mouvement du serpent. Comme expliqué ci-dessus, le serpent se déplace le long du vecteur de coordonnées (dirx, diry). Ainsi, chaque fois que nous appellerons la méthode move que je vais définir ici, le serpent se déplacera du même montant.
Dans cette méthode de déplacement, on vérifie que les coordonnées de la tête du serpent correspondent à celles de la pomme à manger. Si c'est le cas, le serpent vient de manger la pomme. Le joueur marque un point, mais plus important encore, nous devons entreprendre quatre actions :
Néanmoins, dans la méthode de déplacement, il faut vérifier que le joueur n'a pas commis l'erreur de toucher un élément du serpent avec la tête. Si tel est le cas, la partie est perdue, et on recommence ! Pour ce faire, nous appelons la méthode init de la classe Snake présentée ci-dessus.
Maintenant, nous devons compléter la méthode de déplacement en déplaçant réellement le serpent. Pour ce faire, nous ajoutons dirx et diry aux coordonnées de la tête du serpent. Cela nous donne une nouvelle tête à ajouter. Vous remarquerez également que le déplacement du serpent se fait intelligemment en retirant la queue à chaque fois et en ajoutant une nouvelle tête. Cela évite de devoir mettre à jour la position de tous les éléments du serpent.
Terminez en pensant à mettre à jour la nouvelle tête. D'ailleurs, vous aurez également remarqué que lorsque la tête du serpent franchit une limite du plateau, nous la faisons se déplacer vers le côté opposé du plateau. Cela s'applique à la fois à la largeur et à la longueur.
Cela nous donne le code suivant pour la méthode move :
Notre Serpent peut être affiché à l'écran. Notre Serpent peut être déplacé en appelant sa méthode move. Que nous manque-t-il ?
Il nous manque l'implémentation du GameLoop de notre jeu !
Sans ce GameLoop, qui appellera les méthodes move et draw à intervalles réguliers, le Snake ne pourra pas bouger. Dans ce qui suit, nous allons vous montrer comment implémenter correctement un GameLoop en JavaScript, en laissant au navigateur le soin de l'appeler quand bon lui semble afin de ne pas bloquer le fil de rendu de la page Web du jeu.
Pour ce faire, nous utiliserons la méthode requestAnimationFrame de la fenêtre objet JavaScript standard. Le navigateur adaptera alors les fps maximum qu'il peut prendre en charge à l'ordinateur ou au smartphone sur lequel la page Web sera utilisée.
Dans notre méthode gameloop, nous allons ensuite décorréler le nombre de fps pris en charge par le navigateur du nombre de fps auquel nous souhaitons déplacer notre serpent. Nous n’appellerons les méthodes move et draw que lorsque nous serons dans la plage d’images par seconde définie précédemment.
Il est important de mettre à jour les coordonnées du vecteur de mouvement du serpent en fonction de l'état des quatre touches directionnelles : haut, bas, gauche et droite.
Enfin, nous appelons GameLoop, déléguant au navigateur la tâche de choisir le meilleur moment pour le faire. Cela nous donne le code suivant pour le GameLoop :
Pour permettre au Serpent d'être déplacé en fonction des touches directionnelles enfoncées par le joueur, nous utilisons les événements keydown et keyup. Pour chacun de ces événements, nous appellerons une méthode de la classe Snake. Logiquement, ce sera pressdown pour l'événement keydown et pressup pour l'événement keyup.
Nous mettons à jour la valeur des propriétés de la classe Snake liées en fonction de ce que le joueur fait avec ces clés. Comme vous pouvez le constater, nous ne bloquons pas le jeu en mettant directement à jour la position du serpent. Au lieu de cela, nous mettons à jour l’état dans la méthode gameloop, qui est appelée à intervalles réguliers.
Pour réaliser ce jeu Snake, nous devons assembler les différents éléments. On récupère l'objet Canvas via son ID. Ensuite, on obtient le contexte 2D lié à ce Canvas. Appliquez les dimensions souhaitées. Nous créons un objet Snake, en passant les différentes valeurs attendues en paramètres, y compris le nombre de cellules du tableau.
Ajoutez les écouteurs d'événements pour les événements keydown et keyup.
Finalement, il ne reste plus qu'à appeler une fois la boucle de jeu de notre Snake pour lancer la partie. Cela nous donne le code complet suivant pour le célèbre jeu Snake réalisé avec l'API Canvas et l'infernal couple HTML5/JavaScript Web :
Notre Snake terminé, il est temps de le tester dans un navigateur Web pour voir si la magie Snake opère à nouveau, comme elle le faisait lorsque Nokia dominait outrageusement le monde mobile :
A partir de ce jeu Snake, vous pouvez imaginer plusieurs améliorations possibles. Par exemple, vous pourriez ajouter un son à chaque fois que le serpent mange la pomme. Vous pouvez utiliser l'API Web Storage de HTML5 pour stocker le meilleur score local d'un joueur. De cette façon, lorsqu'un joueur bat son meilleur score, vous pouvez afficher un message de félicitations. Les possibilités sont infinies et votre seule limite, comme toujours en programmation, est votre imagination.
Ce tutoriel est également visible sur YouTube sur la chaîne SSaurel :
Également publié ici .