Pong en javascript – intégrer de l’intelligence artificielle

Gérer l’intelligence artificielle est l’objet de la huitième partie consacrée au développement d’un jeu vidéo html5 javascript. L’objectif du jour est de gérer l’intelligence artificielle de l’adversaire et notamment son déplacement.

Prérequis pour gérer l’intelligence artificielle

Avoir lu les tutoriaux consacrés à l’initialisation du projet Coder le jeu vidéo Pong. La mise en place de l’environnement du jeu constitué du terrain, du filet, des raquettes, de la balle et du score Coder le jeu vidéo Pong – Raquettes et Balle. L’animation de la balle Coder le jeu vidéo Pong – Animer la balle et au contrôle de la raquette par le joueur à l’aide du clavier Coder le jeu vidéo Pong – Animer les raquettes. Le contrôle de la raquette par le joueur à l’aide de la souris Coder le jeu vidéo Pong – Controle à la souris. Le renvoi de la balle par les raquettes Coder le jeu video pong – Renvoi de la balle. La gestion des effets sonores Coder le jeu video pong – Ajout des effets sonores.

Le principe

La raquette IA désigne la raquette dirigée par l’intelligence artificielle.

Rien de très complexe en terme d’intelligence artificielle pour un jeu comme Pong. Pour commencer, vous devez gérer deux cas :
– lorsque la balle se dirige vers la raquette IA (de la gauche vers la droite);
– lorsque la balle se dirige en sens inverse de la direction de la raquette IA (de la droite vers la gauche).

Lorsque la balle se dirige vers la raquette IA, l’IA doit chercher à renvoyer la balle. Elle doit donc suivre le mouvement de la balle :
– lorsque la balle monte, l’IA dirige sa raquette vers le haut;
– lorsque la balle descend, l’IA dirige sa raquette vers le bas.

Lorsque la balle se dirige en sens inverse, l’IA doit ramener sa raquette au centre du terrain.

Le code javascript

La première chose à déterminer est le sens dans laquelle la balle se dirige afin de gérer les deux cas présentés précédemment.

Voici le code dédié au déplacement de la balle.

move : function() {
 this.posX += this.directionX * this.speed;
 this.posY += this.directionY * this.speed;
}

Pour le déplacement, ce code utilise deux propriétés de l’objet ball sur chacun des axes (horizontal abscisse X et vertical ordonnée Y) que sont directionX et directionY.

directionX indique le sens de la balle sur l’axe des abscisses et directionY sur l’axe des ordonnées.

La valeur 1 indique un déplacement dans le sens positif de l’axe. De la gauche vers la droite sur l’axe horizontal et du haut vers le bas sur l’axe vertical.
La valeur -1 indique un déplacement dans le sens négatif de l’axe. De la droite vers la gauche sur l’axe horizontal et du bas vers le haut sur l’axe vertical.

C’est à partir de la propriété directionX que vous allez déterminer quand l’intelligence artificielle suit la balle et quand l’intelligence artificielle se recentre :
directionX à 1, la balle vient vers la raquette de l’intelligence artificielle. L’intelligence artificielle suit la balle;
directionX à -1, la balle va vers le joueur. L’intelligence artificielle se recentre sur le terrain.

Pour gérer l’intelligence artificielle, je vous propose de créer le namespace javascript dédié game.ai.

Créez un nouveau fichier nommé game.ai.js en y intégrant le code suivante.

game.ai = {
}

Dans ce namespace javascript dédié au jeu html5 pong, ajoutez les propriétés player et ball.

game.ai = {
 player : null,
 ball : null
}

Pourquoi ajouter ces 2 propriétés alors qu’elles existent dans le namespace javascript game ?
Par simple soucis de lisibilité du code ainsi qu’une volonté de minimiser les couplages.

Les propriétés player et ball sont nulles à l’initialisation, il convient de créer une méthode dédiée à leur initialisation.

game.ai = {
 player : null,
 ball : null,
 
 setPlayerAndBall : function(player, ball) {
  this.player = player;
  this.ball = ball;
 }
}

Ceci fait, il reste à déterminer une fonction qui assure le déplacement par l’intelligence artificielle.

game.ai = {
 player : null,
 ball : null,
 ....
 move : function() {
 }
}

Cette méthode va déterminer quand l’intelligence artificielle se recentre et quand elle suit la balle. Conformément à la stratégie choisie au début de cet article. L’IA suit la balle quand elle s’approche, l’IA se recentre lorsqu’elle s’éloigne.

Souvenez vous que le sens de la balle détermine le mouvement de l’IA. S’ajoute aussi la position du joueur : à gauche ou à droite.

Pour cela, ajoutez une propriété aux objets player (playerOne et playerTwo) qui indique la position du joueur :

const game = {
 ....
 playerOne : {
  width : 10,
  height : 50,
  color : "#FFFFFF",
  posX : 30,
  posY : 200,
  goUp : false,
  goDown : false,
  originalPosition : "left"
 },
 
 playerTwo : {
  width : 10,
  height : 50,
  color : "#FFFFFF",
  posX : 650,
  posY : 200,
  goUp : false,
  goDown : false,
  originalPosition : "right"
 },
 ....
}

playerOne est le joueur de gauche d’où originalPosition : « left ».
playerTwo est le joueur de droite d’où originalPosition : « right ».

Ainsi il est possible de choisir en IA soit le playerOne, soit playerTwo.

Deux mouvements sont possibles :
– suivre la balle;
– se recentrer.

Créez deux méthodes dédiées à ces deux mouvements au sein du namespace game.ai, followBall et goCenter.

game.ai = {
 player : null,
 ball : null,
 
 setPlayerAndBall : function(player, ball) {
  this.player = player;
  this.ball = ball;
 },
 
 move : function() {
 },
 
 followBall : function() {
 },
 
 goCenter : function() {
 }
}

Ces deux fonctions seront appelées depuis la fonction move selon le sens de déplacement de la balle par rapport à la raquette.

game.ai = {
 ....
 move : function() {
  if ( this.ball.directionX == 1 ) {
   if ( this.player.originalPosition == "right" ) {

    this.followBall();
   }
   if ( this.player.originalPosition == "left" ) {

    this.goCenter();
   }
  } else {
   if ( this.player.originalPosition == "right" ) {

    this.goCenter();
   }
   if ( this.player.originalPosition == "left" ) {

    this.followBall();
   }
  }
 },
 ....
}

Il ne reste plus qu’à définir les deux fonctions followBall et goCenter.

Pour followBall (suivre la balle), le principe est de regarder quelle est la position de la raquette par rapport à la balle :
– si la raquette est en dessous, la raquette doit monter;
– si la raquette est au dessus, la raquette doit descendre.

Ce qui donne en javascript.

game.ai = {
 ....
 followBall : function() {
  if ( this.ball.posY < this.player.posY + this.player.height/2 ) {

   this.player.posY--;
  } else if ( this.ball.posY > this.player.posY + this.player.height/2 ) {

   this.player.posY++;
  }
 },
 ....
}

Pour goCenter (aller eu centre), le principe est de regarder quelle est la position de la raquette par rapport au centre du terrain :
– si la raquette est en dessous, la raquette monte;
– si la raquette est au dessus, la raquette descend.

Ce qui donne en javascript.

game.ai = {
 ....
 goCenter : function() {
  if ( this.player.posY + this.player.height/2 > game.groundHeight / 2 ) {
   this.player.posY--;
  } else if ( this.player.posY + this.player.height/2 < game.groundHeight / 2 ) {
   this.player.posY++;
  }
 }
 ....
}

N’oubliez pas d’ajouter le fichier game.ai.js en dépendance javascript dans le fichier html. Initialisez dans la fonction init les objets player et ball du namespace game.ai. Et faites aussi appel à la fonction move dans la boucle principale.

init : function() {
 ....
 this.wallSound = new Audio("./sound/wall.ogg");
 this.playerSound = new Audio("./sound/player.ogg");
 
 game.ai.setPlayerAndBall(this.playerTwo, this.ball);
},

const main = function() {

 game.clearLayer(game.playersBallLayer);
 game.movePlayers();
 game.displayPlayers();
 game.moveBall();
 game.ai.move();
 game.collideBallWithPlayersAndAction();

 requestAnimId = window.requestAnimationFrame(main); 
}

Vous avez maintenant une intelligence artificielle fonctionnelle.

Apprenez à créer un jeu vidéo en une soirée.

Accessible à tous.

Nombre de places limité.

Voir l'événement

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