Gérer les interactions physiques dans un jeu vidéo

Suite de la série d’articles consacrés à la création d’un shooter avec phaser.js, le précédent étant consacré à la gestion d’un game over.

Pour accroitre la difficulté, on donne aux météorites des trajectoires qui ne soient ni verticales, ni horizontales et fait en sorte que lorsque 2 d’entre elles se percutent leurs trajectoires respectives soient affectées.

Toujours pour que le déroulement du jeu soit uniforme d’un joueur à l’autre, depuis create on définit un 2nd RandomDataGenerator pour tirer au hasard et de manière ordonnée les vitesses des météorites sur chacun des 2 axes au sein de la méthode spawnMeteor, dont on va une nouvelle fois changer la signature en supprimant les paramètres de vitesse.

create() {....
 this.randomDataMeteor = new Phaser.Math.RandomDataGenerator(999);
....}
....
spawnMeteor(meteorView, angularVelocity, scene, layer) {....
 meteor.start(this.randomDataMeteor.between(-200, 200),this.randomDataMeteor.between(20, 300));
....}

Sans oublier de modifier aussi son appel par le biais du timer.

this.meteorTimer = this.time.addEvent( {.... 
 this.spawnMeteor(meteorView,15,this,this.gameLayer);
....},

En l’état, les trajectoires sont bien variées mais les collisions restent sans effet. Souvenez-vous des overlap et des collider dont nous avions parlés précédemment : ici pour qu’il y ait interaction on définit un collider entre le groupe meteorGroup et lui-même toujours au sein de create. Et il n’y a que ça à faire.

create() {....
 this.physics.add.collider(this.meteorGroup, this.meteorGroup);
....}

Tout marche à une imperfection près : les interactions ne sont pas des plus précises. Les objets étant par défaut affublés d’un masque de collision rectangulaire, les changements de trajectoire se font en conséquence. Phaser.js permet de gérer des masques de collision complexes.

Nonobstant, on fait un choix plus simple : les météorites étant à peu près circulaires, l’usage d’un masque du même acabit suffit à donner plus de réalisme. On le spécifie au sein de la fonction spawnMeteor par appelant la méthode setCircle qui prend en paramètre le rayon du masque en pixels. Les météorites faisant 64 pixels de côté, on passe la valeur 32.

Il reste à déterminer la restitution ou la transmission des forces d’un objet à l’autre lorsqu’ils se percutent et c’est la méthode setBounce qui la spécifie sur les 2 axes X et Y. Plus les nombres sont proches de zéro, plus les forces seront absorbées et moins la collision aura d’effet.

spawnMeteor(meteorView, scene, layer) {
 const meteor = this.meteorGroup.get(this.randomData.between(0, 600),50,meteorView);
 meteor.setBounce(1,1);
 meteor.setCircle(32);
 ....}

A présent, on a un système plus réaliste. Il existe de nombreuses méthodes qui permettent de paramétrer les interactions telles que la masse, les frictions pour simuler des matériaux plus ou moins dures ou réguliers. Bref, il y a de quoi faire.

En guise de conclusion

Phaser.js étant riche de fonctionnalités, on en a exploré une petite partie sur la base du modèle objet javascript ES6. Au fur et à mesure des ajouts, le code s’est alourdi avec une méthode update qui a pris du poids.

Pour éviter ce type de désagrément, des ajustements seraient donc bien utiles en termes de découplage et d’architecture en retravaillant entre autres le comportement, certes sommaire, de la météorite par le biais d’une machine à états finis, ou en gérant le contrôle du joueur sous la forme d’un composant réutilisable. La méthode update doit être la plus petite possible. Mais c’est une autre histoire….

Explore l'univers de la création de jeux vidéo

Saisis ton prénom et ton e-mail pour recevoir ton livre GRATUIT et commence ton voyage ludique dès maintenant.

Bravo, jette un œil à ta boite mail pour télécharger ton guide.