Coder le jeu video html5 pong – Debut et fin de partie




 

Dixième partie consacrée au développement du jeu vidéo html5 javascript: le développement de Pong est bientôt terminé. Si vous jouez en l’état, les points sont comptés mais une partie ne se termine jamais. Je vous propose donc de faire en sorte qu’une partie ait un début et une fin.


 

Prérequis

Avoir lu les tutoriaux suivants :
– 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;
– le 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 html5 pong – Renvoi de la balle;
– l’ajout du son lorsque la balle cogne un mur ou une raquette Coder le jeu vidéo Pong – Ajout du son.
– l’intelligence artificielle Coder le jeu video html5 pong – Intelligence Artificielle;
– la Coder le jeu video html5 pong – Gestion du score et engagement.

 

Le principe

Une partie débute lorsque le joueur clique sur un bouton dédié Start Game. L’appui sur ce bouton ne fait pas de lancé de balle qui reste assuré par la barre espace du clavier. Une partie se déroule jusqu’à ce que l’un des joueurs ait marqué 10 points.

 

Ajout du bouton pour démarrer la partie

La partie doit démarrer sur une action du joueur, en l’occurrence un simple bouton. Ajoutez manuellement ce bouton dans la page html via la balise ‹input type=’button’/› :
– avec un id égal à startGame;
– et une value positionnée à Start Game.

<input id="startGame" type="button" value="Start Game">

Par contre, cela va nécessiter quelques petites transformations et pas des moindres : si vous ajoutez le code html ci-dessus directement entre les balises html, le bouton ne sera pas visible puisque recouvert par le canvas html5 noir.

Pour afficher le bouton Start Game, commencez par l’encapsuler dans une balise div comme ceci :

....
  <div id="menu"><input id="startGame" type="button" value="Start Game"></div>
</html>

A l’exécution, vous ne voyez toujours pas le bouton.

Ceci est normal compte tenu de la construction de la fonction createLayer: elle crée un canvas html5.

Elle laisse cependant la possibilité de l’encapsuler ou pas dans un container html5.

Si le canvas html5 n’est pas encapsulé, il sera rattaché à page html5 et disposé brutalement aux coordonnées indiquées par les 2 derniers paramètres de la fonction. C’est le cas auquel vous êtes confronté.

Voir le code ci-dessous:

....
this.groundLayer= game.display.createLayer("terrain", this.groundWidth, this.groundHeight, undefined, 0, "#000000", 0, 0); 
....  
this.scoreLayer = game.display.createLayer("score", this.groundWidth, this.groundHeight, undefined, 1, undefined, 0, 0);
....
this.playersBallLayer = game.display.createLayer("joueursetballe", this.groundWidth, this.groundHeight, undefined, 2, undefined, 0, 0);  
....

Si le canvas html5 est encapsulé, c’est le container html5 qui sera placé aux coordonnées indiquées dans les 2 derniers paramètres.

Du fait de l’ajout du bouton Start Game, l’écran de jeu commence à prendre forme et il convient de le concevoir proprement en dédiant des zones de l’écran à des fonctions particulières, dans le cas présent:
– une partie dédiée au menu (existante par le biais de la balise div menu);
– une partie dédiée au terrain de jeu à ajouter.

....
  <div id="menu"><input id="startGame" type="button" value="Start Game"></div>
  <div id="divGame"></div>
</html>

Au préalable, ajoutez au namespace game une nouvelle propriété désignant la balise div divGame:

var game = {
  ....  
  wallSound : null,
  playerSound : null,
  
  divGame : null,
  ....
}

Il reste à rattacher le layer à la balise div divGame et de placer ce container en dessous du bouton:

init : function() {
  this.divGame = document.getElementById("divGame");
	
  this.groundLayer= game.display.createLayer("terrain", this.groundWidth, this.groundHeight, this.divGame, 0, "#000000", 10, 50); 
  game.display.drawRectangleInLayer(this.groundLayer, this.netWidth, this.groundHeight, this.netColor, this.groundWidth/2 - this.netWidth/2, 0);
    
  this.scoreLayer = game.display.createLayer("score", this.groundWidth, this.groundHeight, this.divGame, 1, undefined, 10, 50);
  game.display.drawTextInLayer(this.scoreLayer , "SCORE", "10px Arial", "#FF0000", 10, 10);
    
  this.playersBallLayer = game.display.createLayer("joueursetballe", this.groundWidth, this.groundHeight, this.divGame, 2, undefined, 10, 50);  
  game.display.drawTextInLayer(this.playersBallLayer, "JOUEURSETBALLE", "10px Arial", "#FF0000", 100, 100);
    
  this.displayScore(0,0);
  this.displayBall(200,200);
  this.displayPlayers();
   
  this.initKeyboard(game.control.onKeyDown, game.control.onKeyUp);
  this.initMouse(game.control.onMouseMove);
	
  this.wallSound = new Audio("./sound/wall.ogg");
  this.playerSound = new Audio("./sound/player.ogg");

  game.ai.setPlayerAndBall(this.playerTwo, this.ball);

},

A l’affichage :

La fait que vous ayez 2 parties distinctes permettra ensuite de remodeler votre interface relativement facilement.

 

La gestion du bouton pour démarrer la partie

Déclencher une partie ou ne pas déclencher une partie. Attention à bien différencier le fait de déclencher une partie et de lancer la balle qui sont 2 états distincts en sachant que l’un est dépendant de l’autre.

On ne peut lancer la balle sans avoir au préalable démarrer une partie.

Le code tel qu’il est intègre une propriété de l’objet ball nommée inGame qui indique si la balle est en jeu ou pas. L’état d’une partie démarrée, pour le moment, n’existe pas.

Commencez par ajouter cette propriété au namespace game en la nommant gameOn et en la fixant à false: au lancement du jeu, la partie n’est pas lancée.

var game = {
  ....
  gameOn : false,
  startGameButton : null,
  ....

Cette nouvelle variable est à positionnée à true lorsque l’utilisateur clique sur le bouton Start Game.

Il faut abonner le bouton à l’événement onclick qui génère un appel vers une fonction qui modifie la valeur de la propriété gameOn en la positionnant à true.

Je vous propose de créer une nouvelle méthode dans le namespace game qui abonne le click sur le bouton Start Game à une fonction du namespace game.control onStartGameClickButton qui positionne gameOn à true :

Dans le namespace game :

var game = {
  ....
  initStartGameButton : function() {
    this.startGameButton.onclick = game.control.onStartGameClickButton;
  },
  ....
}

Dans le namespace game.control :

game.control = {
  ....
  onStartGameClickButton : function() {
    game.gameOn = true;
  }
  ....
}

Ensuite, il faut rendre le lancement de la balle dépendant de l’état de la partie: démarrée ou non démarrée.
Cette modification est à faire au niveau du namespace game.control dans la clause relative à l’appui sur la barre espace:

game.control = {  
  mousePointer : null,
   
  onKeyDown : function(event) {
    ....
    if ( event.keyCode == game.keycode.SPACEBAR && !game.ball.inGame ) { 
      game.ball.inGame = true;
      game.ball.posX = game.playerOne.posX + game.playerOne.width;
      game.ball.posY = game.playerOne.posY;
      game.ball.directionX = 1;
      game.ball.directionY = 1;
    }
  },
  ....
}

qui devient (la condition game.gameOn a été ajoutée):

game.control = {
  ....
  onKeyDown : function(event) {
    ....
    if ( event.keyCode == game.keycode.SPACEBAR && !game.ball.inGame && game.gameOn ) { 
      game.ball.inGame = true;
      game.ball.posX = game.playerOne.posX + game.playerOne.width;
      game.ball.posY = game.playerOne.posY;
      game.ball.directionX = 1;
      game.ball.directionY = 1;
    }
  },
  ....
}

Désormais, la partie démarre sur action du joueur. Pour l’arrêt de la partie, c’est dans le paragraphe suivant.

 

Arrêt de la partie

Comme indiqué en introduction, une partie doit s’arrêter dès que l’un des deux joueurs a marqué 10 points. Un joueur marque un point lorsque son adversaire perd la balle.

C’est la fonction lostBall du namespace game qui détecte la perte de la balle et incrémente le compteur de points.

C’est donc cette même fonction qui devrait stopper la partie une fois les 10 points atteints.

var game = {
  ....
  lostBall : function() {
    if ( this.ball.lost(this.playerOne) ) {
      this.playerTwo.score++;
      this.ball.inGame = false;
	  
      if ( this.playerOne.ai ) { 
        setTimeout(game.ai.startBall(), 3000);
      }
    } else if ( this.ball.lost(this.playerTwo) ) {
      this.playerOne.score++;
      this.ball.inGame = false;

      if ( this.playerTwo.ai ) { 
        setTimeout(game.ai.startBall(), 3000);
      }
    }
	
    this.scoreLayer.clear();
    this.displayScore(this.playerOne.score, this.playerTwo.score);
  },
  ....
}

Il suffit de rajouter un test sur le score de chaque joueur qui, s’il est supérieur à 9, stoppe la partie.

L’indicateur game.gameOn indique si une partie est en cours (gameOn=true) ou pas (gameOn=false). Une simple valorisation de game.gameOn à false suffit à stopper la partie.

Dans le code :

var game = {
  ....
  lostBall : function() {
    if ( this.ball.lost(this.playerOne) ) {
      this.playerTwo.score++;
      if ( this.playerTwo.score > 9 ) {
        this.gameOn = false;
      } else {
        this.ball.inGame = false;
	  
        if ( this.playerOne.ai ) { 
          setTimeout(game.ai.startBall(), 3000);
        }
      }
    } else if ( this.ball.lost(this.playerTwo) ) {
      this.playerOne.score++;
      if ( this.playerOne.score > 9 ) {
        this.gameOn = false;
      } else {
        this.ball.inGame = false;

        if ( this.playerTwo.ai ) { 
          setTimeout(game.ai.startBall(), 3000);
        }
      }
    }
	
    this.scoreLayer.clear();
    this.displayScore(this.playerOne.score, this.playerTwo.score);
  },
  ....
}

La partie est bien stoppée. Cependant, lorsque vous redémarrez une nouvelle partie via le bouton Start Game, le comportement est chaotique : la balle continue sa course là où elle était, le score s’incrémente et la partie s’arrête.

Tout cela relève du fait que l’état de la balle ainsi que le score ne sont pas réinitialisés.

Deux choix possibles pour cette réinitialisation :
– la réaliser au sein de la fonction lostBall;
– la réaliser lorsque le joueur démarre une partie via le bouton Start Game.

Pour la clarté du code, je vous conseille d’encapsuler tout ce qui est relatif à la réinitialisation d’une partie dans une fonction dédiée rattachée au namespace javascript game: la réinitialisation du jeu et les paramètres sont propres au jeu développé donc non réutilisables.

var game = {
  ....
  reinitGame : function() {
  },
  ....
}

Ensuite, que faut-il réinitialiser ?
– le fait que la balle ne soit plus en jeu;
– le score de chaque joueur et son affichage.

Le résultat :

var game = {
  ....
  reinitGame : function() {
    this.ball.inGame = false;
    this.playerOne.score = 0;
    this.playerTwo.score = 0;
    this.scoreLayer.clear();
    this.displayScore(this.playerOne.score, this.playerTwo.score);
  },
  ....
}

Mon choix est de l’appeler lorsque le joueur clique sur le bouton Start Game: la fonction appelée dans ce cas est onStartGameClickButton du namespace javascript game.control.

Cet appel se fait uniquement si aucune partie n’est en cours (game.gameOn=false).

game.control = {
  ....
  onStartGameClickButton : function() {
    if ( !game.gameOn ) {
      game.reinitGame();
      game.gameOn = true;
    }
  }
}

Prochain article sur la trajectoire et la vitesse de la balle pour rendre le jeu plus attractif et jouable et c’est PROCHAINEMENT.

 
Le code de démo a désactivé la fonction move de l’intelligence artificielle.
Pour voir en live le code, cliquez sur Pong

 

Si vous avez aimé cet article, partagez le.

 

Si vous constatez des coquilles, ou avez des remarques à faire ou encore souhaitez manifester votre satisfaction de ce tuto, n’hésitez pas les commentaires sont faits pour ça.

 

Posté dans html5, pongTaggé développer pong, pong html5, pong javascript, tutoriel html5, tutoriel jeu vidéo, tutoriel pong  |  2 commentaires

2 réponses à "Coder le jeu video html5 pong – Debut et fin de partie"

Répondre

*