Coder le jeu video html5 pong – contrôle tactile

 

Les tablettes et les smartphones sont de nos jours incontournables, implémenter le contrôle tactile des raquettes dans le jeu video pong est plus que pertinent. C’est l’objet de cette seizième partie consacrée au développement d’un jeu vidéo html5 javascript.

 

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;
– l’ajout d’un début et d’une fin à une partie Coder le jeu video html5 pong – début et fin de partie;
– la vitesse et la trajectoire de la balle Coder le jeu video html5 pong – vitesse et trajectoire de la balle;
– le look plus moderne Coder le jeu video html5 pong – Changement de look;
– l’adaptation du jeu vidéo à la taille de l’écran sur lequel il est exécuté Coder le jeu video html5 pong – adaptation de la taille de l’écran;
– le décor du jeu vidéo Coder le jeu video html5 pong – le décor;
– la correction de quelques imperfections quelques réajustements.

Le principe

Le code que vous allez implémenter consiste simplement à ajouter la gestion des événements relatifs aux fonctions tactiles. Ces événements fonctionnent comme ceux relatifs au clavier ou à la souris, donc pas de gros changements à l’horizon.

 

Empêcher le zoom de l’écran

Autoriser le zoom pourrait altérer l’expérience du joueur. Il pourrait malencontreusement zoomer durant une partie. Imaginez, il y aurait de quoi le mettre en rage.

La balise meta viewport n’est utilisée que sur les smartphones et tablettes, elle n’a d’incidence que lorsque le code est exécuté sur smartphone ou tablette.

Elle représente la surface de l’écran du mobile.

Pour faire simple, la propriété width de viewport fixée à la valeur device-width va faire en sorte que le viewport (la largeur de l’écran) du mobile affiche 100% de la largeur de la page web.

Pour empêcher le zoom, il suffit de fixer les propriétés initial-scale, et maximum-scale à 1.0.

Ajoutez au fichier source pong.html juste après la balise html, la balise meta suivante:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />

Et plus de zoom possible.

 

De nouveaux événements

Comme tout système d’interaction en javascript, le gestion du contrôle tactile passe par le gestionnaire d’événements qui est asynchrone.

Au même titre que vous utilisez l’événement onmousemove pour la gestion de la souris dans e jeu, il existe un événement similaire dédié au contrôle tactile: l’événement ontouchmove.

Implémentation

Tout comme l’événement onmousemove, l’événement ontouchmove permet de capturer les coordonnées du doigt en contact avec l’écran.

Le mode de gestion va donc être proche voire identique.

Pour stocker les coordonnées du pointeur de la souris, vous utilisez la propriété mousePointer de l’objet game.control. Comme son nom l’indique, elle est dédiée au pointeur de la souris.

Commme je le disais précédemment, traitement identique pour l’événement ontouchmove avec capture des coordonnées tactiles.

Je vous propose donc de renommer cette propriété en genericPointer. Ce genericPointer sert à stocker aussi bien les coordonnées du pointeur de la souris que celle du pointeur tactile (le doigt). Pensez à modifier à tous les endroits où cette variable est utilisée.

Toujours dans le namespace game.control, créez une nouvelle méthode onTouchMove sur la base de la méthode onMouseMove. Faites un simple copier/coller, vous la modifierez ensuite.

game.control = {
  ...
  onTouchMove : function(event) {
   
    game.control.controlSystem = "MOUSE";
	
    if ( event ) {
      game.control.genericPointer = event.clientY - conf.MOUSECORRECTIONPOSY;
    }

    if ( game.control.genericPointer > game.playerOne.sprite.posY ) {
      game.playerOne.goDown = true;
      game.playerOne.goUp = false;
    } else if ( game.control.genericPointer < game.playerOne.sprite.posY ) {
      game.playerOne.goDown = false;
      game.playerOne.goUp = true;
    } else {
      game.playerOne.goDown = false;
      game.playerOne.goUp = false;
    }
  },
  ...
}

Première modification à opérer: game.control.controlSystem indicatrice en temps réel du mode de contrôle utilisé valorisé à TOUCH.

Deuxième modification à opérer: game.control.genericPointer coordonnée du pointeur à valoriser dans le contexte tactile dont la structure de données event est différente de celle du contexte de la souris.

Après modification vous obtenez:

game.control = {
  ...
  onTouchMove : function(event) {
   
    game.control.controlSystem = "TOUCH";
	
    if ( event ) {
      game.control.genericPointer = event.touches[0].pageY - conf.MOUSECORRECTIONPOSY;
    }

    if ( game.control.genericPointer > game.playerOne.sprite.posY ) {
      game.playerOne.goDown = true;
      game.playerOne.goUp = false;
    } else if ( game.control.genericPointer < game.playerOne.sprite.posY ) {
      game.playerOne.goDown = false;
      game.playerOne.goUp = true;
    } else {
      game.playerOne.goDown = false;
      game.playerOne.goUp = false;
    }
  },
  ...
}

Dernière modification à apporter sur cette fonction: la constante conf.MOUSECORRECTIONPOSY est utilisée pour gérer le décalage qu’il y a entre le pointeur de la souris est la raquette.

Ne sachant pas si ce décalage est identique en mode tactile, je vous invite à créer une nouvelle constante TOUCHCORRECTIONPOSY dans le namespace conf.

Et de remplacer dans la methode onTouchMove MOUSECORRECTIONPOSY par TOUCHCORRECTIONPOSY.

Voilà ce qu’il en est après modification:

game.control = {
  ...
  onTouchMove : function(event) {
   
    game.control.controlSystem = "TOUCH";
	
    if ( event ) {
      game.control.genericPointer = event.touches[0].pageY - conf.MOUSECORRECTIONPOSY;
    }

    if ( game.control.genericPointer > game.playerOne.sprite.posY ) {
      game.playerOne.goDown = true;
      game.playerOne.goUp = false;
    } else if ( game.control.genericPointer < game.playerOne.sprite.posY ) {
      game.playerOne.goDown = false;
      game.playerOne.goUp = true;
    } else {
      game.playerOne.goDown = false;
      game.playerOne.goUp = false;
    }
  },
  ...
}

Les parties de code communes à onMouseMove et onTouchMove sont bien entendu factorisables.

Il reste une dernière chose à réaliser du côté du namespace game et la méthode movePlayers qui utilisent la propriété dont j’ai reparlé ci-dessus game.control.controlSystem.

La fonction movePlayers avant la modification

var game = {
...
   movePlayers : function() {
  
     var up;
     var down;
	
     if ( game.control.controlSystem == "KEYBOARD" ) {
       if ( game.playerOne.goUp ) {
         up = true;
         down= false;
       } else if ( game.playerOne.goDown ) {
         up = false;
         down= true;
       }
     } else if ( game.control.controlSystem == "MOUSE" ) {
      if (game.playerOne.goUp && game.playerOne.sprite.posY > game.control.genericPointer ) {
        up = true;
        down= false;
      } else if (game.playerOne.goDown && game.playerOne.sprite.posY < game.control.genericPointer ) {
        up = false;
        down= true;
      }
     }	
	
     if ( up && game.playerOne.sprite.posY > 0 )
       game.playerOne.sprite.posY-=5;
     else if ( down && game.playerOne.sprite.posY < game.groundHeight - game.playerOne.sprite.height )
       game.playerOne.sprite.posY+=5;
	  
  },
..
}

Deux tests sont réalisés sur game.control.controlSystem qui servent à indiquer que le contrôle se fait à la souris ou au clavier.

J’admets que le second test est un peu superflu. En continuant dans la même logique, ce second test deviendrait avec une clause relatif au contrôle tactile (game.control.controlSystem == « TOUCH »):

var game = {
...
   movePlayers : function() {
  
     var up;
     var down;
	
     if ( game.control.controlSystem == "KEYBOARD" ) {
       ....
     } else if ( game.control.controlSystem == "MOUSE" || game.control.controlSystem == "TOUCH" ) {

     }	
	
     if ( up && game.playerOne.sprite.posY > 0 )
       game.playerOne.sprite.posY-=5;
     else if ( down && game.playerOne.sprite.posY < game.groundHeight - game.playerOne.sprite.height )
       game.playerOne.sprite.posY+=5;
	  
   },
...
}

Ou on supprime simplement la clause if.

Ce qui donne au final:

var game = {
...
   movePlayers : function() {
  
     var up;
     var down;
	
     if ( game.control.controlSystem == "KEYBOARD" ) {
       if ( game.playerOne.goUp ) {
         up = true;
         down= false;
       } else if ( game.playerOne.goDown ) {
         up = false;
         down= true;
       }
     } else {
       if (game.playerOne.goUp && game.playerOne.sprite.posY > game.control.genericPointer ) {
         up = true;
         down= false;
       } else if (game.playerOne.goDown && game.playerOne.sprite.posY < game.control.genericPointer ) {
         up = false;
         down= true;
       }
     }	
	
      if ( up && game.playerOne.sprite.posY > 0 )
        game.playerOne.sprite.posY-=5;
      else if ( down && game.playerOne.sprite.posY < game.groundHeight - game.playerOne.sprite.height )
        game.playerOne.sprite.posY+=5;
	  
  },
..
}

Vous avez un contrôle tactile de votre raquette mais vous n’avez pas de clavier et il est donc impossible de lancer la balle.

Bref, il vous faut ajouter l’engagement de la balle avec vos doigts. Je vous propose de lancer a balle par simple touché de deux doigts sur l’écran de jeu.

Je vous propose d’opérer selon la méthode suivante:
– détecter le nombre de doigts qui touchent l’écran;
– si deux doigts touchent l’écran, lancer la balle si toutes les conditions sont réunies.

L’événement touchstart se déclenche dès qu’un doigt touche l’élément auquel est rattaché l’événement. Restez sur la même logique, ne changez rien à l’élément rattaché: cela reste toujours la page html en l’occurrence l’élément window.

Dans le namespace game.control, ajoutez une fonction qui renvoie le nombre de doigts qui touchent l’écran:

game.control = {
  ...
  fingersOnTouchStart : function(event) {
    var returnValue = 0;
    game.control.controlSystem = "TOUCH";
	
    if ( event ) {
      returnValue = event.targetTouches.length;
    }
    return returnValue;
  },
  ...
}

Puis créez une fonction onTouchStart appelée lorsque l’événement touchstart sera levé. C’est cette fonction qui lance la balle.

game.control = {
  ...
  onTouchStart : function(event) {
    if ( game.control.fingersOnTouchStart(event) == 2 && !game.ball.inGame && game.gameOn ) {
      game.ball.inGame = true;
      game.ball.sprite.posX = game.playerOne.sprite.posX + game.playerOne.sprite.width;
      game.ball.sprite.posY = game.playerOne.sprite.posY;
      game.ball.directionX = 1;
      game.ball.directionY = 1;
    }
  },
  ...
}

Remarquez que le code encapsulé est identique à celui utilisé pour lancer la balle avec la barre espace du clavier (bad smells).

Enfin dans le namespace game, rattachez la fonction game.control.onTouchStart à l’événement touchstart rattaché au window.

Il existe une fonction game.initTouch qui initialise l’événement sur le contrôle de la raquette avec le doigt. Modifiez la pour y intégrer le code relatif à la fonction game.control.onTouchStart.

var game = {
  ...
  initTouch : function(onTouchMoveFunction, onTouchStartFunction) {
    window.ontouchmove = onTouchMoveFunction;
    window.ontouchstart = onTouchStartFunction;
  },
  ...
}

La signature a évolué avec un paramètre supplémentaire, celui de la fonction appelée sur l’événement touchstart.

L’appel à game.initTouch est donc aussi à modifier en conséquence.

Vous pouvez maintenant jouer sur votre tablette, smartphone ou votre micro.

 
Pour voir en live le code et de préférence en testant à partir d’une tablette ou d’un smartphone, cliquez sur Pong

 

Si vous avez aimé cet article, partagez le.

 

Si vous constatez des coquilles, ou avez des remarques, une autre solution ou encore souhaitez manifester votre satisfaction de ce tuto, commentez.

 

Posté dans html5, pongTaggé canvas html5, canvas image, jeu video html5, tuto html5  |  Laisser un commentaire

Répondre