Flixel : Afficher et animer un Sprite

Dans le dernier tutoriel Flash je vous ai présenté Flixel, une bibliothèque très puissante qui permet de créer rapidement des jeux type arcade (mais pas que 😉 ). Aujourd’hui nous allons poursuivre notre découverte et voir comment afficher, animer et déplacer un personnage en utilisant la classe FlxSprite. Je vous invite à récupérer la feuille de sprite ci-dessous qui sera utilisée tout au long de ce tutoriel.

spritesheet-mario
Une feuille de sprite avec Mario

Les Sprite sheet

Une « Sprite Sheet » ou feuille de Sprite en Français, est une image qui contient en général un personnage avec toutes ses animations. Vous pouvez voir sur l’image du dessus qu’il y a 4 animations : bas, gauche, droite, haut. Lorsque vous utiliserez une feuille de Sprite il faudra récupérer les informations suivantes avant d’aller plus loin :

  1. Largeur et hauteur d’un Sprite
  2. Largeur et hauteur de la feuille de Sprite
  3. Nombre d’image par animation

L’image que nous utilisons ici fait 200 pixels de largeur pour 276 pixels de hauteur et il y a 4 animations différentes. On obtient donc la largeur et la hauteur d’un sprite comme suis :

var spriteWidth:int = 200 / 4; // soit 50px
var spriteHeight:int = 277 / 4; // soit 69px

Flixel ne va pas afficher l’image entière mais juste une partie qui correspondra à un Sprite parmi ceux présents sur la feuille. Vous pouvez voir l’image comme un tableau à 2 dimensions où chaque image de personnage correspond à un indice du tableau. Ainsi la première image de la feuille a l’index 0, la deuxième 1, la troisième 2, etc… Le sens de lecture de gauche à droite et du haut vers le bas. L’indice de la dernière image de notre feuille de Sprite est donc 15 😛 ((4 x 8) – 1).

Maintenant que nous avons ces informations, passons à la pratique ! La première étape conscite à créer un objet de type FlxSprite, il sera un conteneur graphique représentant notre personnage. Cette classe contient une méthode addAnimation() qui va découper et afficher pour nous, les bonnes images, quand il faudra. Dans un premier temps créez simplement un nouveau projet Flixel et copiez l’image dans le dossier assets (à créer si vous ne l’avez pas déjà fait).

Pour créer un nouveau Sprite avec Flixel, il faut instancier un objet de type FlxSprite, ou dérivé.

var sprite:FlxSprite = new FlxSprite(positionX, positionY);

Ce code va créer un objet graphique de type FlxSprite aux coordonnées positionX, positionY et il n’aura aucune apparence. Pour lui attacher une image vous pouvez soit le faire à la construction, soit le faire après avec la méthode loadGraphic().

// A la création
var sprite:FlxSprite = new FlxSprite(positionX, positionY, image);

// Ou après la création
sprite.loadGraphic(image);

On peut créer directement un Sprite avec une seule image mais dans notre cas on veut un sprite animé qui utilise une feuille de Sprite, on ne peux donc pas donner l’image avec toutes les animations au constructeur de FlxSprite. La méthode loadGraphic() sera donc utilisée, elle prend plusieurs paramètres qui permettent d’indiquer à Flixel si l’image à utilisée doit être découpée et si le Sprite doit être animé.

loadGraphic(image:Class, animer:Boolean, inverser:Boolean, largeur:int, hauteur:int)

Les noms des paramètres sont assez explicites je pense 😉 Vous aurez remarqué que les 2 dernières valeurs permettent de spécifier la taille final de l’image (le sprite animé). Il est donc très important d’avoir des feuilles de Sprites correctement réalisées, avec des valeurs en hauteur et largeur juste (on ne veux pas un sprite de 45.45654px de largeur par exemple). Passons maintenant au code.

Main.as : Le point de démarrage

package
{
  import org.flixel.FlxGame;

  [SWF(width="640", height="480", backgroundColor="#00000000")]
  public class Main extends FlxGame
  {
    public function Main():void
    {
      super(640, 480, PlayState);
    }
  }
}

On se contente d’initialiser Flixel en dérivant FlxGame, le jeu sera lancé avec une résolution de 640×480. On passe en 3éme paramètre la classe à instancier après l’initialisation, PlayState dans notre cas.

PlayState.as : L’écran de jeu

package
{
  import org.flixel.FlxState;

  public class PlayState extends FlxState
  {
    // Le joueur (Sprite) animé
    private var _player:Player;

    // Le constructeur reste vide
    public function PlayState() { }

    // Création du Joueur et ajout à la liste d'affichage
    override public function create():void
    {
      _player = new Player();
      add(_player);
    }
  }
}

La classe PlayState représente l’écran de jeu et elle doit dériver de FlxState. On surcharge la méthode create() pour initialiser l’objet Player (voir plus bas) qui est le joueur. Toutes les modifications logiques ou visuelles du joueur sont réalisées dans la classe Player.

Player.as : Le joueur, ses animations, sa gestion

package
{
  import org.flixel.FlxPoint;
  import org.flixel.FlxSprite;
  import org.flixel.FlxG;

  public class Player extends FlxSprite
  {
    [Embed("../assets/spritesheet-mario.png")]
    private const SpriteSheetMario:Class;

    public function Player()
    {
      super(0, 0);

       loadGraphic(SpriteSheetMario, true, false, 50, 69);

	// Création de ses animations
	// 1 - Nom de l'animation
	// 2 - partie de l'image à prendre pour cette animation
	// 3 - Vitesse de transition entre chaque image
	// 4 - Répétition à l'arrêt
	addAnimation("down", [0, 1, 2, 3], 10, false);
	addAnimation("left", [4, 5, 6, 7], 10, false);
	addAnimation("right", [8, 9, 10, 11], 10, false);
	addAnimation("up", [12, 13, 14, 15], 10, false);

	// Position au centre de l'écran
	this.x = (FlxG.width / 2) - (this.width / 2);
	this.y = (FlxG.height / 2) - (this.height / 2);
      }

      override public function update():void
      {
        super.update();

	// Déplacement du personnage
	// Mise à jour de l'animation à jouer
	if (FlxG.keys.UP)
	{
	  this.y--;
	  play("up");
	}

	if (FlxG.keys.DOWN)
	{
	  this.y++;
	  play("down");
	}

	if (FlxG.keys.LEFT)
	{
	  this.x--;
	  play("left");
	}

	if (FlxG.keys.RIGHT)
	{
	  this.x++;
	  play("right");
	}
      }
   }
}

La première étape consiste à charger la feuille de Sprite, c’est une image donc rien de plus simple. Le constructeur de la classe mère est ensuite appelé et positionne l’objet aux coordonnées 0, 0 par rapport au coin en haut à gauche de l’écran. Un appel à la méthode loadGraphic() permet de configurer l’objet graphique en lui attachant une image et en spécifiant que ce sprite sera animé (valeur true en 2éme paramètre).

addAnimation("down", [0, 1, 2, 3], 10, false);

C’est dans cette méthode que les animations sont explicitement déclarées, on passe en premier le nom de l’animation puis un tableau d’indice qui correspondent à une ou plusieurs images de la feuille de Sprite. Enfin on spécifie le temps de transition entre chaque image et on désactive la répétition.

Si on prend l’extrait de code précédent vous pouvez voir que j’ai passé en paramètre un tableau de 4 valeurs (0, 1, 2, 3). C’est le fameux tableau d’indice qui permet d’identifier chaque image de la feuille de Sprite. L’animation « bas » par exemple utilise les images 0, 1, 2 et 3.

if (FlxG.keys.RIGHT)
{
  this.x++;
  play("right");
}

Jouer une animation est vraiment simple, il faut utiliser la méthode play() avec le nom de l’animation en paramètre et le tour est joué il n’y a pas besoin de faire autre chose ! Vous aurez remarqué qu’on utilise aussi l’objet FlxG pour récupérer la touche pressée. FlxG.keys.#TOUCHE# prendra la valeur true si la touche #TOUCHE# est pressée. Je vous invite à consulter la documentation pour plus d’informations.

Conclusion

Nous avons vue aujourd’hui comment charger, afficher, animer et déplacer un Sprite avec Flixel. Le Framework nous simplifie vraiment beaucoup le travail car il suffit juste d’avoir une feuille de Sprite bien faite, avec les bonnes informations (les tailles et le nombre d’animations) pour avoir un personnage animé très rapidement.

Flixel propose encore beaucoup de fonctionnalités magiques, comme la caméra qui vous permettra de créer des niveaux avec scrolling en 2 lignes de code 🙂 Nous verrons ça très prochainement dans un article dédié à la camera et son utilisation. Vous pouvez retrouver le projet entier sur mon espace Github.