Un jeu HTML5 : graphismes, textes, effets, collisions et sons

Dans ce chapitre nous allons voir comment Pixi permet d’ajouter des graphismes, du texte, et des effets. D’autre part nous verrons comment on peut intégrer du son avec HTML. Nous finirons en étudiant la question importante de la détection des collisions.

Les graphismes

Pixi est équipé de quelques méthodes pour dessiner des graphismes :

  • moveTo : déplace le stylo,

  • lineTo : trace une ligne,

  • drawCircle : dessine un cercle,

  • drawEllipse : dessine une ellipse,

  • drawRect : dessine un rectangle,

  • drawRoundedRect : dessine un rectangle avec les coins arrondis,

  • quadraticCurveTo : dessine une courbe de Bezier.

D’autre part on peut déterminer le style de ligne et le remplissage :

  • beginFill : définit la couleur de remplissage,

  • lineStyle : définit l’épaisseur, la couleur et la transparence de la ligne.

Voici un exemple récapitulatif :

<!DOCTYPE HTML>
<html>
<head>
  <title>Cours pixi</title>
  <meta charset="UTF-8">
  <script src="../js/pixi.js"></script>
  <style>
    canvas {
      margin: 0 auto;
      display: block;
    }
  </style>
</head>
<body>
  <script>
    var renderer = PIXI.autoDetectRenderer(400, 300, {antialias: true});
    document.body.appendChild(renderer.view);
    var stage = new PIXI.Container();

    var graphics = new PIXI.Graphics();

    graphics.beginFill(0x00ffff);
    graphics.lineStyle(5, 0x0000ff, 1);

    graphics.drawCircle(70, 70, 60);
    graphics.drawEllipse(180, 70, 40, 60);

    graphics.beginFill(0xff00ff);
    graphics.lineStyle(3, 0x00ff00, 1);
    graphics.drawRect(240, 10, 120, 40);
    graphics.drawRoundedRect(240, 60, 120, 70, 20);

    graphics.beginFill(0xff0000);
    graphics.lineStyle(5, 0x0000ff, 1);
    graphics.moveTo(20, 160);
    graphics.lineTo(100, 180);
    graphics.lineTo(80, 240);
    graphics.lineTo(30, 250);
    graphics.endFill();

    graphics.beginFill(0x7fff00);
    graphics.lineStyle(5, 0x00aa00, 1);
    graphics.moveTo(200, 160);
    graphics.quadraticCurveTo(220, 300, 300, 220);
    graphics.endFill();

    stage.addChild(graphics);
    renderer.render(stage);

  </script>
</body>
</html>

 Avec ce rendu :

img01

Remarquez l’activation de  l’option antialias qui permet d’obtenir des courbes lissées.

Le texte

Police classique

Créer du texte avec Pixi est très facile, voici un exemple avec un texte de base et un texte stylisé :

<!DOCTYPE HTML>
<html>
<head>
  <title>Cours pixi</title>
  <meta charset="UTF-8">
  <script src="../js/pixi.js"></script>
  <style>
    canvas {
      margin: 0 auto;
      display: block;
    }
  </style>
</head>
<body>
  <script>
    var renderer = PIXI.autoDetectRenderer(400, 300, {backgroundColor : 0xaaaaaa});
    document.body.appendChild(renderer.view);
    var stage = new PIXI.Container();

    var texte1 = new PIXI.Text('Texte basique');
    texte1.position.set(20, 20);
    stage.addChild(texte1);

    var style = {
      font : 'bold italic 36px Helvetica',
      fill : '#dddd42',
      stroke : '#aaaa20',
      strokeThickness : 4,
      dropShadow : true,
      dropShadowColor : '#888800',
      dropShadowAngle : Math.PI / 6,
      dropShadowDistance : 4
    };

    var texte2 = new PIXI.Text('Texte stylisé\nsur deux lignes', style);
    texte2.position.set(20, 60);
    stage.addChild(texte2);

    renderer.render(stage);

  </script>
</body>
</html>

img02

Police Google

Si vous voulez utiliser un police de Google il faut prévoir de la charger, voici un exemple :

<script>
  var renderer = PIXI.autoDetectRenderer(400, 300);
  document.body.appendChild(renderer.view);
  var stage = new PIXI.Container();

  window.WebFontConfig = {
      google: { families: ['Snippet'] },
      active: function () {
        var texte = new PIXI.Text(
            'Un texte avec\nune police Google',
            {
                font: '32px Snippet',
                fill: 'white',
                stroke: '#888888',
                strokeThickness: 4
            }
        );
        texte.position.set(20, 20);
        stage.addChild(texte);
        renderer.render(stage);
      }
  };

  (function(){
    var wf = document.createElement("script");
    wf.src = ('https:' === document.location.protocol ? 'https' : 'http') +
            '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.async = 'true';
    document.head.appendChild(wf);
  })();
</script>

 Avec ce résultat :

img03

Tiling sprites et fond en mouvement

Les tiling sprites sont un peu spéciaux parce que leur texture est un motif qui peut se raccorder à lui-même et ainsi se répéter pour couvrir une grande surface.

Regardez cette image :

briques

C’est un simple morceau de mur en briques. Maintenant si j’en aligne 3 x 3 :

briquesplus

On se rend compte qu’ils se raccordent parfaitement.

Voici comment procéder avec Pixi :

<script>
  var renderer = PIXI.autoDetectRenderer(192, 128);
  document.body.appendChild(renderer.view);
  var stage = new PIXI.Container();

  var sprite = PIXI.extras.TilingSprite.fromImage("img/briques.png", renderer.width, renderer.height);
  stage.addChild(sprite);

  gameLoop();

  function gameLoop(){
    requestAnimationFrame(gameLoop);
    renderer.render(stage);
  }
</script>

  La méthode TilingSprite  construit automatiquement l’image finale. Il suffit de transmettre comme paramètres :

  1. la texture,

  2. la largeur totale,

  3. la hauteur totale.

On utilise souvent cet effet pour faire défiler un fond, il suffit d’ajouter une ligne au code précédent pour le réaliser :

function gameLoop(){
  requestAnimationFrame(gameLoop);
  sprite.tilePosition.x -= 1;
  renderer.render(stage);
}

 Vous avez maintenant le fond qui défile et on aura l’impression que tout objet placé devant se déplace en sens inverse.

Les sons

Avant HTML5 il n’y avait aucun standard pour diffuser des sons sur le web, il fallait obligatoirement utiliser un plugin. Maintenant on dispose de la balise <audio>.

Cette balise est très simple à utiliser, voici un exemple :

<audio controls>
  <source src="sounds/sound.mp3" type="audio/mp3">
  Votre navigateur ne supporte pas la balise audio !
</audio>

 Le fait d’avoir ajouté controls  fait apparaître dans le navigateur un panneau de contrôle :

img04

Evidemment lorsqu’on crée un jeu on ne veut pas voir apparaître ce panneau et on se contente de cette syntaxe :

<audio id="monson" src="sounds/sound.mp3" preload="auto" autoplay="autoplay" loop="loop"></audio>

  On voit deux attributs supplémentaires :

  • preload : indique qu’on veut précharger le son,

  • autoplay : indique que le son doit démarrer tout seul,

  • loop : indique que le son doit jouer en boucle.

D’autre part il est indiqué d’ajouter un identifiant pour gérer ensuite le son avec JavaScript :

var monson = document.getElementById("monson");

 Les principales méthodes à connaître sont :

  • play : pour jouer le son,

  • pause : pour faire une pause,

  • stop : pour stopper le son.

Tout cela est bien pratique mais… si ça fonctionne très bien avec la plupart des navigateurs il reste encore des problèmes avec les mobiles. En attendant que la compatibilité soit parfaite il vaut mieux utiliser une librairie, la meilleure à mes yeux étant howler.js :

img05

L’utilisation est d’une grande simplicité et la documentation du site est très bien faite, vous pouvez vous y reporter directement.

Les collisions

Un jeu nécessite pratiquement toujours à un moment un système de détection de collisions. Pixi ne propose rien à ce niveau parce qu’il se contente de gérer le rendu. Heureusement il existe de très nombreuses librairies dans ce domaine. Ma préférée est sat.js :

img06

Le principe est simple, pour chaque sprite concerné on définit une forme qui sert pour la détection. On a le choix entre cercle, polygone et boîte.

Par exemple nous avons ce sprite :

image

Etant donné sa forme on va définir un polygone :

image1

Le degré de précision du polygone dépend de la précision de la détection désirée. Ce polygone est défini par les coordonnées de ses sommets. La librairie utilise des vecteurs, pour notre sprite ça pourrait donner quelque chose comme ça :

var polygon = new SAT.Polygon(new SAT.Vector(sprite.x, sprite.y), [
  new SAT.Vector(2, 37),
  new SAT.Vector(73, 2),
  new SAT.Vector(125, 45),
  new SAT.Vector(84, 125),
  new SAT.Vector(23, 120)
]);

 Maintenant si on veut détecter la collision entre deux sprites identiques on utilise la méthode de détection entre deux polygones :

var collision = SAT.testPolygonPolygon(sprite1, sprite2, response);

 Si collision est vrai alors c’est qu’il y a collision, sinon c’est qu’il n’y a pas collision. Le paramètre response donne d’autres informations si vous désirez plus de précision sur la collision.

Reportez-vous à la documentation du site pour plus de précisions.

En résumé

Dans ce chapitre on a :

  • appris à dessiner des cercles, ellipses, rectangles et courbes de Bezier,

  • vu comment créer du texte simple, stylisé et avec une police de Google,

  • découvert les tiling sprites et vu un exemple d’utilisation,

  • vu la gestion des sons en HTML ainsi que la librairie howler.js,

  • vu les collisions avec la librairie sat.js.

Laisser un commentaire