Archive pour août 2011

Animer des sprites avec HTML5 (canvas) et un peu de jQuery (sans CSS)

Dimanche 14 août 2011

Nous avions vu ensemble, il y a un bon moment, comment animer des sprites avec jquery et css. La méthode était efficace, mais loin d’être propre et pratique. En vue de réaliser un site/jeu, je me penche sur une méthode plus efficace pour animer des sprites : le canvas.

Le canvas affiche autant des formes vectorielles, comme vu dans l’article précédent, que des images ou des vidéos, l’intérêt principal étant qu’on peut interagir de façon très poussée avec ces images.

La méthode est semblable à celle utilisé avec CSS, on n’affiche que la zone du sprite souhaitée et on décale l’image pour créer une animation, seulement ici pas besoin de zone de masque, c’est le canvas qui gère tout.

Je passe rapidement sur les bases pour afficher une image dans la balise canvas :

$(document).ready(function(){
	var canvas = $('#myCanvas');
	var context = canvas.get(0).getContext("2d");

	var image = new Image();
	image.src = "exemple.jpg";
	$(image).load(function(){
		context.drawImage(image, 0, 0);
	});
});

Alors ici que fait-on ? Tout simplement nous déclarons une nouvelle image à laquelle nous attribuons une source, et une fois que cette image est chargée nous l’affichons dans le canvas la première valeur numérique étant la position horizontale et la seconde verticale.

Avec canvas il est très facile de n’afficher qu’une partie de l’image. Pour cela on utilise la ligne suivante :

	context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

Pas de panique je vous indique à quoi correspondent ces valeurs.

  • sx = la distance horizontale entre la coin haut gauche de l’image et le coin haut gauche de l’aperçu.
  • sy = la distance verticale entre la coin haut gauche de l’image et le coin haut gauche de l’aperçu.
  • sw = la largeur de l’aperçu
  • sh = la hauteur de l’aperçu
  • dx = la position horizontale du rendu de l’aperçu dans le canvas
  • dy = la position verticale du rendu de l’aperçu dans le canvas
  • dw = la largeur du rendu de l’aperçu dans le canvas
  • dh = la hauteur du rendu de l’aperçu dans le canvas

Les 4 premières valeurs numériques servent à définir l’aperçu par rapport à la source et les 4 dernières à définir la position et la taille dans le canvas

A partir de là nous pouvons nous amuser. Dans mon exemple j’ai repris le sprite de mon petit bonhomme qui court tout nu… (Pas pris le temps de faire les habits…) Chaque ‘frame’ du personnage fait 100×100 pixel, j’y ajoute un élément qui servira pour le décor en le répétant.

Voici le résultat que nous allons atteindre avec le script qui suit :
Démonstration d’animation de sprites avec canvas

Je commence par vous montrer le script que je vais un peu détailler tout du long :


La partie un peu compliquée de ce script concerne l'animation du sprite en elle-même.
La première raison est que pour rendre la course fluide nous rechargeons très fréquemment l'animation (toutes les 33 millisecondes), or nous avons très peu de frames pour la gestuelle du personnage que nous souhaitons animer seulement toutes les 150 ou 160 millisecondes, soit environ 5 fois moins que l'animation de déplacement. Pour cela nous utilisons le compteur et toutes les 5 fois que l'animation se joue nous changerons l'affichage du personnage et afin de savoir à quel moment précis, nous utilisons une expression régulière qui analyse le compteur pour savoir si celui-ci est un multiple de 5. Si le compteur divisé par 5 donne un chiffre entier, alors c'est un multiple de 5 et donc on peu changer l'affichage.

J'ai pensé à cette méthode, ce n'est peut-être pas la plus efficace, mais elle marche, n'hésitez pas à proposer des alternatives.

La deuxième difficultés vient du fait que les animations de gestuelles n'ont pas le même nombre de frames, 3 pour immobile et 4 pour la course. Et en plus ne se déroule pas de la même manière. Pour la version statique, l'animation doit repasser par l'affichage du milieu pour faire une boucle, alors que pour la course, une fois à la 4ème frame, on retourne à celle du début.

Pour cela on utilise un autre compteur qui s'incrémente 5 fois plus lentement que le premier, qui permet de savoir où nous en sommes de l'animation de gestuelle du perso. Dans le cas immobile, une fois arrivé à la dernière frame, on indique qu'il faut retourner en arrière (décrémenter) puis repartir une fois revenu à la première frame. (ré-incrémenter) Dans le cas de la course, une fois arrivé à la dernière frame on se replace simplement sur la première.

Une fois que nous savons tout cela, il suffit tout de récupérer le contexte de l'animation, le personnage court-il? dans quelle direction... ? grâce un listener des touches gauche et droite et changer les variables.

J'espère avoir été assez précis dans mes explications, n'hésitez pas à me poser des questions ou suggérer d'autres méthodes.

Tout ceci n'est qu'un avant goût d'un projet bien plus gros, en chantier actuellement, mais qui s'annonce très excitant.

Je vous recommande chaudement le livre de robhawkes : Foundation HTML5 canvas.

A bientôt