Animations par affichages successifs
La méthode la plus simple pour obtenir un effet d’animation consiste à afficher successivement plusieurs images présentant les différentes phases d’un mouvement. Le nombre d’images qu’il faut afficher en une seconde pour obtenir une animation fluide dépend de la vitesse et du type de mouvement. Si le mouvement est lent, on peut se contenter d’un nombre d’images faible (Une horloge animée ne nécessite qu’une image par seconde). Si le mouvement est rapide, il ne faudra pas descendre en dessous de 16 images seconde. Il n’est pas envisageable d’afficher de longues séquences animées composées d’images de la taille de l’écran en 16 millions de couleurs à moins de disposer d’un équipement professionnel.
Afin d'optimiser une animation, trois options sont possibles :
- Réduire la taille des images
- Réduire le nombre d’images par seconde
- Réduire le nombre de couleurs
Animations par déplacement d’image
L’animation par déplacement d’image consiste à afficher une image fixe appelée sprite à différentes positions suuccessives de l’écran. Ces positions sont calculées en fonction d’une trajectoire définie préalablement. La vitesse de déplacement peut être fixe ou variable. Chaque fois que le programme déplace une image, il doit d’abord l’effacer avec le fond avant de l’afficher à sa nouvelle position. Tout déplacement d’image consiste en fait à déplacer trois images : une image du fond, un masque de la taille de l’image sur lequel s’ajoute l’image.
Les images déplacées sont toujours de forme rectangulaire, ce qui peut poser un problème. En effet, il est rare que les objets représentés soient rectangulaires. Si l’image déplacée a un fond identique à celui du décor (une couleur unie) alors la solution consiste à déplacer un morceau de fond en même temps. Si le fond n’est pas uni alors l’image déplacée doit avoir un fond transparent, et donc posséder une couleur déclarée comme transparente.
Animations par déplacement d’images animées
Il est tout à fait possible d’afficher de la même façon une image animée. Il suffit pour cela de créer les différentes images correspondant aux phases de l’animation. Pour chaque image, on crée également un masque qui permette de voir le fond sur lequel se déplace l’animation. On affiche alors successivement les images selon la trajectoire du mouvement choisi.
Remarque
Lorsque l’affichage est effectué en couleurs indexées, c’est à dire à l’aide d’une palette de 256 couleurs, il est impératif que tous les éléments utilisent la même palette.
Principe de l’affichage
Comme nous l'avons vu, une image est composée de pixels. Chaque pixel est structuré en octet. Chaque octet est structuré en bits. Une image en 256 couleurs possède une résolution tonale de 8 bits. Chaque pixel est donc codé sur 8 bits pour notre exemple: xxxxxxxx Chaque bit peut prendre la valeur 0 ou 1
Nous avons une image à l'écran (le fond) sur laquelle nous voulons voir se déplacer un chien (le sprite) :
Pour l'ordinateur, le chien n'existe pas : le sprite n'est qu'une zone rectangulaire qui contient des informations colorées. Nous voulons que les pixels du chien soient superposés à ceux du fond, mais que ces derniers apparaissent là où le chien ne doit pas apparaitre. Nous voulons donc faire apparaître deux types de pixels: ceux du chien et ceux du fond.
Cependant, le sprite ne contient pas que les pixels du chien, il y a aussi d'autres pixels qui doivent êtres invisibles. Dans notre exemple, ce sont les pixels de la zone blanche qui entoure le chien. Ce sont ces mêmes pixels auxquels sera assigné une valeur transparente.
Cette transparence n'est possible et n'existe que par l'utilisation de fonctions logiques. En effet, quand on affiche une image à l'écran, elle écrase ce qu'il y a en dessous. Son mode d'affichage logique correspond non pas à effacer mais donner une nouvelle valeur aux pixels. Or un sprite possède des pixels qui doivent donc ne pas changer les pixels du fond. Ces pixels transparent ont pourtant forcément une valeur. Il faut donc jouer sur la relation entre la valeur des pixels transparents et celle des pixels du fond. Le problème vient de ce que pour l'ordinateur ces pixels transparents ont le même statut au niveau informationnel (les bits) que les pixels non transparents du sprite. Il en résulte que lorsqu'on affiche un sprite avec des zones transparentes sur un fond on doit dire à l'ordinateur que : - certains pixels (les transparent) doivent prendre tous la même valeur - que la valeur des pixels transparent doit n'avoir aucune influence sur le pixels du fond - que les pixels du fond sur lesquels apparaitront les pixels apparents du sprite doivent prendre la valeur de ces derniers.
Nous avons deux cas de figure : les pixels transparents sur le fond et les pixels non transparent sur le fond.
L'ordinateur doit donc prendre en compte trois types de valeurs : celles du fond, celles du sprite non transparent et celles du sprite transparent. Il y a donc une opération à faire. Celle-ci est forcément faite dans un mode logique puisque c'est le mode de fonctionement de l'ordinateur. Ce sera donc soit un OR, un AND ou un NOT (les trois opérations de base de l'ordinateur). Le problème se complique pour des questions de respect des couleur des pixels non transparents du sprite. Nous ne rentrerons pas dans les détails mais il en résulte la nécessité d'utiliser un masque sur lequel sera superposé le sprite :
Chaque pixel non transparent du sprite doit être posé sur un pixel noir du masque. Les autres pixels du masque sont transparents.
Prenons un pixel non transparent et un pixel transparent de notre animation :
Pixel non transparent | Pixel transparent | |
Pixel du sprite | 00101110 | 00000000 |
Pixel du masque | 00000000 | 11111111 |
Pixel du fond | 01101001 | 01001110 |
Dans un premier temps, on effectue une opération logique ET entre l'image du masque et l'image du fond :
pixel non transparent : 01101001 ET 00000000 = 00000000, donc la couleur noire du pixel du masque écrase celle du fond.
pixel transparent : 01001110 ET 11111111 = 01001110, donc la couleur du pixel de l'image du fond est respectée par celle du pixel transparent du masque.
Dans un second temps, on effectue une opération logique OU entre le résultat obtenu ci-dessus et le pixel de l'image du sprite :
pixel non transparent : 00000000 OU 00101110 = 00101110, donc la valeur du pixel du sprite s'impose à la valeur du sprite du masque.
pixel transparent : 01001110 OU 00000000 = 01001110 , donc le fond est respecté.
On s'aperçoit que la valeur binaire du pixel transparent n'est pas la même dans le sprite et le masque, mais ceci est nécessaire pour le respect de la transparence.