Fév 28, 2016 Jeu HTML5

Un jeu HTML5 : tileset, atlas et animation de sprite

Lorsqu’on a plusieurs images à charger, et c’est toujours le cas lorsqu’on crée un jeu, plutôt que de charger les images une par une, ce qui est très gourmand en ressources, on préfère créer une seule image contenant toutes les images, communément appelé tileset. Dans ce chapitre nous allons voir comment créer tileset. Nous verrons également comment créer un atlas pour facilement gérer un tilset.

Un tileset

Un tileset (aussi appelé spritesheet) est donc un ensemble d’images rassemblées dans une seule image. Si vous tapez « tileset » dans un moteur de recherche vous allez en trouver des milliers comme par exemple celui-ci :

img01

Pour utiliser ces différentes images il faut évidemment connaître à la fois leur position et leur dimension. Mais une fois qu’on a cela il est facile d’aller piocher ce dont on a besoin. Remarquez que les images peuvent avoir une taille quelconque.

Les spritesheets sont très utilisés pour stocker les images des différentes étapes d’une animation, par exemple :

img02

Il suffit alors d’afficher les images l’une après l’autre dans l’ordre pour créer l’animation, comme au cinéma !

Mais comment connaître emplacement et taille de chaque image ?

Tileset et atlas avec TexturePacker

Un atlas est un fichier JSON associé à un tileset qui renseigne précisément sur les images présentes. Voici un exemple du contenu :

{"frames": {

"balloon01.png":
{
  "frame": {"x":0,"y":0,"w":30,"h":83},
  "rotated": false,
  "trimmed": false,
  "spriteSourceSize": {"x":0,"y":0,"w":30,"h":83},
  "sourceSize": {"w":30,"h":83},
  "pivot": {"x":0.5,"y":0.5}
},
"balloon02.png":
{
  "frame": {"x":30,"y":0,"w":30,"h":83},
  "rotated": false,
  "trimmed": false,
  "spriteSourceSize": {"x":0,"y":0,"w":30,"h":83},
  "sourceSize": {"w":30,"h":83},
  "pivot": {"x":0.5,"y":0.5}
}
}

 

Vous voyez que tout est bien rangé et on peut connaître :

  • l’emplacement,

  • la rotation,

  • la dimension,

  • l’emplacement du pivot (ce que j’ai appelé point de référence dans le précédent chapitre),

On ne va évidemment pas créer cet atlas de façon manuelle, ça serait vraiment laborieux ! Il existe de très bons logiciels qui savent bien faire ça. Mon préféré est TexturePacker qui propose une version gratuite suffisante pour une utilisation de base. Je vous suggère donc de télécharger et installer ce logiciel.

A l’ouverture il se présente ainsi :

img03

Cliquez sur « Use Free Version ». Ce qui vous mène ici :

img04

Maintenant il vous faut vos images individuelles, par exemple vous avez ces trois images :

img05

Chacune est dans son fichier individuel. Vous les mettez toutes les trois dans un même dossier :

img06

Maintenant faite glisser ce dossier dans la zone centrale de TexturePacker :

img07

Un truc un peu agaçant de ce programme lorsqu’on n’a que la version gratuite c’est qu’il applique d’office des options qui n’existent que dans la version payante (il faut bien encourager les gens à l’acheter…), il faut donc les désactiver pour obtenir un résultat correct.

Spécifiez le format de sortie JSON (Hash) ainsi que l’emplacement et le nom du fichier à générer (dans le même dossier pour simplifier) :

img08

Là si vous cliquez sur le bouton de publication :

img09

Vous allez récolter quelques erreurs :

img10

Dans les réglages à droite repérez et désactivez les options correspondantes jusqu’à obtenir ceci :

img11

Vous devez avoir deux fichiers supplémentaires :

img13

On trouve le tileset :

chauvesouris

Et l’atlas :

{"frames": {

"chauvesouris01.png":
{
  "frame": {"x":0,"y":0,"w":266,"h":140},
  "rotated": false,
  "trimmed": false,
  "spriteSourceSize": {"x":0,"y":0,"w":266,"h":140},
  "sourceSize": {"w":266,"h":140},
  "pivot": {"x":0.5,"y":0.5}
},
"chauvesouris02.png":
{
  "frame": {"x":266,"y":0,"w":140,"h":163},
  "rotated": false,
  "trimmed": false,
  "spriteSourceSize": {"x":0,"y":0,"w":140,"h":163},
  "sourceSize": {"w":140,"h":163},
  "pivot": {"x":0.5,"y":0.5}
},
"chauvesouris03.png":
{
  "frame": {"x":406,"y":0,"w":380,"h":200},
  "rotated": false,
  "trimmed": false,
  "spriteSourceSize": {"x":0,"y":0,"w":380,"h":200},
  "sourceSize": {"w":380,"h":200},
  "pivot": {"x":0.5,"y":0.5}
}},
"meta": {
  "app": "http://www.codeandweb.com/texturepacker",
  "version": "1.0",
  "image": "chauvesouris.png",
  "format": "RGBA8888",
  "size": {"w":786,"h":200},
  "scale": "1",
  "smartupdate": "$TexturePacker:SmartUpdate:d23c7536aba56a34faae05811d54c1bc:c02ba29ab528e76c7e45446257a42b7f:120bf91a42ab7a2eec4129068e5d618d$"
}
}

 

On trouve dans cet atlas les renseignements nécessaires pour récupérer les images et aussi des renseignements spécifiques à TexturePacker (meta) que vous pouvez supprimer sans problème.

Utilisation du tileset

Maintenant qu’on a un joli tileset voyons comment Pixi nous permet de l’utiliser.

Récupérer une texture

Pour récupérer une seule texture dans le tileset c’est facile, voici un exemple :

<!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();
    document.body.appendChild(renderer.view);
    var stage = new PIXI.Container();

    PIXI.loader
      .add('chauvesouris/chauvesouris.json')
      .once('complete', setup)
      .load();

    function setup() {
      var chauvesouris = new PIXI.Sprite(PIXI.Texture.fromFrame('chauvesouris01.png'));
      chauvesouris.position.set(200, 150);
      stage.addChild(chauvesouris);
      renderer.render(stage);
    }
  </script>
</body>
</html>

img14

On voit que pour charger le tileset on le fait avec l’atlas :

PIXI.loader.add('chauvesouris/chauvesouris.json')...

 Et ensuite on crée le sprite en récupérant la ressource :

var chauvesouris = new PIXI.Sprite(PIXI.Texture.fromFrame('chauvesouris01.png'));

Récupérer plusieurs textures pour un sprite animé

Pour créer un sprite animé le chargement du tileset est évidemment le même, par contre il faut créer un MovieClip :

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

  PIXI.loader
    .add('chauvesouris/chauvesouris.json')
    .once('complete', setup)
    .load();

  var sprite;

  function setup() {
    var frames = [];
    frames.push(PIXI.Texture.fromFrame("chauvesouris01.png"));
    frames.push(PIXI.Texture.fromFrame("chauvesouris02.png"));
    frames.push(PIXI.Texture.fromFrame("chauvesouris01.png"));
    frames.push(PIXI.Texture.fromFrame("chauvesouris03.png"));
    var chauvesouris = new PIXI.extras.MovieClip(frames);
    chauvesouris.anchor.set(0.5, 0.5);
    chauvesouris.position.set(200, 150);
    chauvesouris.animationSpeed = 0.1;
    chauvesouris.play();
    stage.addChild(chauvesouris);
    gameLoop();
  }

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

 Là on a l’animation en faisant se succéder les images 1, 2, 1 et 3 dans cet ordre en boucle.

On commence par créer et remplir un tableau avec les textures :

var frames = [];
frames.push(PIXI.Texture.fromFrame("chauvesouris01.png"));
frames.push(PIXI.Texture.fromFrame("chauvesouris02.png"));
frames.push(PIXI.Texture.fromFrame("chauvesouris01.png"));
frames.push(PIXI.Texture.fromFrame("chauvesouris03.png"));

 On crée ensuite le MovieClip avec ce tableau :

var chauvesouris = new PIXI.extras.MovieClip(frames);

 On règle le point de référence, la position et la vitesse d’animation (entre 0 et 1) :

chauvesouris.anchor.set(0.5, 0.5);
 chauvesouris.position.set(200, 150);
 chauvesouris.animationSpeed = 0.1;

 Et ensuite on lance l’animation :

chauvesouris.play();

 On retrouve enfin la boucle pour l’animation.

On dispose également de la propriété loop, un booléen normalement vrai pour avoir l’animation en boucle.

On dispose aussi de ces méthodes :

  • stop : pour arrêter l’animation

  • gotoAndPlay : on va sur une image spécifique (avec son numéro) et on démarre l’animation

  • gotoAndStop : on va sur une image spécifique (avec son numéro) et on stoppe l’animation

On peut évidemment déplacer ce sprite animé comme on le ferait pour un sprite non animé.

En résumé

Dans ce chapitre on a :

  • découvert ce qu’est un tileset.

  • appris ce qu’est un atlas.

  • appris à créer un tileset accompagné de son atlas avec TexturePacker.

  • appris à récupérer une texture avec un atlas pour créer un sprite.

  • Appris à récupérer plusieurs textures d’un atlas pour créer un sprite animé.

Laisser un commentaire