Tutoriaux : Interpolation de mouvement
 

Introduction

 
Ce tutoriel explique ce que les anglophones appellent la technique du "easing" : il s'agit de coder le déplacement d'un clip qui doit suivre le curseur de votre souris avec un léger retard. Ce retard peut être défini par deux paramètres a et b que vous pouvez faire varier entre 0 et 1 comme dans l'animation ci-dessous. Déplacez votre souris dans la zone rectangulaire, observez le déplacement du cercle noir puis faites varier a et b à l'aide des glissières.

Nous allons détailler la réalisation de l'animation ci-dessus étape par étape en publiant 4 animations de complexité croissante puis une petite variante vous sera proposée.

 
Dans la bibliothèque
 

- Ouvrez flash et créez un nouveau document de 200 pixels de largeur et de 200 pixels de hauteur.
- Définissez la cadence de l'animation à 25 images par seconde.
- Définissez une couleur d'arrière-plan différente du blanc.
- Créez un nouveau clip que vous nommerez "cercle". Dans ce clip, tracez un cercle noir de 10 pixels de diamètre. A l'aide du panneau "Aligner" (Ctrl+K), centrez ce cercle horizontalement et verticalement.

 
Sur la scène principale
 
- Sur la scène principale, placez une occurrence du clip "cercle". Centrez ce clip horizontalement et verticalement puis dans le panneau "propriétés" nommez cette occurrence "cercle_mc".
 
Le code n°1 et l'animation obtenue
 

Dans le panneau "action" de l'image clé n°1, placez le code ci-dessous.

onEnterFrame = function() {
var dx = _xmouse - cercle_mc._x;
cercle_mc._x += 0.25*dx;
}

 
Commentaires du code n°1
 
On crée une fonction qui sera exécutée à chaque image.
onEnterFrame = function() {
 
On calcule la différence entre l'abscisse de la souris et celle du cercle.
var dx = _xmouse - cercle_mc._x;
 
On ajoute le quart de dx à l'abscisse du cercle. Cette ligne de code est équivalente à :
cercle_mc._x = cercle_mc._x + 0.25*dx; En procédant ainsi, la position du cercle "tend" vers celle de la souris.
cercle_mc._x += 0.25*dx;
 
Fin de la fonction onEnterFrame
}
 
Pour comprendre comment fonctionne ce petit bout de code, supposons que l'abscisse du cercle noir soit égale à 100 et que l'abscisse de la souris soit égale à 200 (on suppose que la souris reste statique). Au lancement de l'animation on suppose que : cercle_mc._x = 100 et que tout au long de l'animation _xmouse = 200. Dans ce cas dx vaut 100 et à l'image suivante on ajoute 25 à l'abscisse du cercle. A l'image n°1, on a donc cercle_mc._x = 125, dx vaut alors 75 et à l'image suivante on ajoute 18.75. A l'image n°2, on a donc : cercle_mc._x = 143.75. En utilisant la fonction trace, on peut ainsi suivre l'évolution numérique de l'abscisse du cercle et de la distance dx. On obtient le tableau suivant dans lequel les données sont arrondies au millième :
 

image

cercle_mc._x

0.25*dx

n°0
n°1
n°2
n°3
n°4
n°5
n°6
n°7
n°8
n°9
n°10
n°11
n°12
n°13
n°14
n°15
n°16
n°17
n°18
n°19
n°20
n°21
n°22
n°23
n°24
n°25
n°26
n°27
n°28
n°29
n°30
n°31
n°32
n°33
n°34
n°35
n°36
n°37

100
125
143.75
157.813
168.359
176.27
182.202
186.652
189.989
192.492
194.369
195.776
196.832
197.624
198.218
198.664
198.998
199.248
199.436
199.577
199.683
199.762
199.822
199.866
199.9
199.925
199.944
199.958
199.968
199.976
199.982
199.987
199.99
199.992
199.994
199.996
199.997
199.998

25
18.75
14.063
10.547
7.91
5.933
4.449
3.337
2.503
1.877
1.408
1.056
0.792
0.594
0.445
0.334
0.251
0.188
0.141
0.106
0.079
0.059
0.045
0.033
0.025
0.019
0.014
0.011
0.008
0.006
0.004
0.003
0.003
0.002
0.001
0.001
0.001
0.001

 
A l'image n°37 (autrement dit en moins de 2 secondes) l'abscisse du cercle est "quasiment" égale à celle de la souris.
 
Le code n°2 et l'animation obtenue
 

Dans le panneau "action" de l'image clé n°1, placez le code ci-dessous.

onEnterFrame = function() {
var dy = _ymouse - cercle_mc._y;
cercle_mc._y += 0.25*dy;
}

 
Commentaires du code n°2
 
Le déplacement obtenu se fait verticalement mais le principe est bien entendu le même ! Dans l'animation suivante, nous allons coupler les deux animations précédentes (déplacement horizontal et vertical) : désormais le déplacement du cercle ne sera plus rectiligne.
 
Le code n°3 et l'animation obtenue
 

Dans le panneau "action" de l'image clé n°1, placez le code ci-dessous.

onEnterFrame = function() {
var dx = _xmouse - cercle_mc._x;
var dy = _ymouse - cercle_mc._y;
cercle_mc._x += 0.25*dx;
cercle_mc._y += 0.25*dy;
}

 
Commentaires du code n°3
 
Je ne vois pas l'intérêt de commenter ce code ligne par ligne ! Il suffit de lire ce qui précède... Pourquoi avoir choisi 0.25 comme coefficient multiplicateur de dx ? En bien, vous pouvez prendre des valeurs comprises entre 0 et 1 : pour zéro, le cercle sera immobile tandis que pour 1, le cercle suivra parfaitement et sans retard le déplacement de votre curseur (à la manière d'un startDrag). Les valeurs intermédiaires vous permettront d'obtenir l'effet recherché... Je vous conseille de créer deux paramètres a et b placés en début de programme et d'observer l'incidence de leur variation sur le déplacement du cercle :
 
a = 0.2;
b = 0.5; 
 
onEnterFrame = function() {
var dx = _xmouse - cercle_mc._x;
var dy = _ymouse - cercle_mc._y;
cercle_mc._x += a*dx;
cercle_mc._y += b*dy;
}
 
On peut également placer plusieurs occurrences du même cercle qui se déplacent simultanément vers la position du curseur avec des valeurs de a et de b propres à chaque occurrence. Avoir des clips qui se déplacent vers le curseur c'est bien mais si l'on veut pouvoir utiliser sa souris pour cliquer sur des boutons ou utiliser des glissières comme dans l'animation qui figure dans l'introduction, il faut pouvoir contraindre le déplacement des clips en les obligeant par exemple à rester à l'intérieur d'une zone rectangulaire. C'est ce que je vous propose d'étudier avec l'animation suivante :
 
Le code n°4 et l'animation obtenue
 

- Modifiez la taille de l'animation : hauteur = 200 pixels, largeur = 400 pixels.
- Dans la bibliothèque, faites un clic droit sur le clip "cercle" et sélectionnez "liaison". Cliquez sur la case à cocher "exporter pour ActionScript" et choisissez "cercle" comme identifiant. Ainsi nous allons pouvoir placer dynamiquement des occurrences du clip cercle sur la scène principale.
- Supprimez l'occurrence du clip "cercle" qui se trouve sur la scène principale.

Dans le panneau "action" de l'image clé n°1, placez le code ci-dessous

 
xmin = 20;
ymin = 20;
xmax = 380;
ymax = 180; n = 10;
 
amin = 0.05;
amax = 0.5;
 
this.createEmptyMovieClip("rectangle_mc", 0);
with(rectangle_mc) {
lineStyle(0, 0x000000, 100);
moveTo(xmin, ymin);
lineTo(xmax, ymin);
lineTo(xmax, ymax);
lineTo(xmin, ymax);
lineTo(xmin, ymin);
}
 
function deplacement () {
var dx = _xmouse - this._x;
var dy = _ymouse - this._y;
this._x += this.a*dx;
this._y += this.a*dy;
if(this._x > xmax) {this._x = xmax;} else if(this._x < xmin) {this._x = xmin;}
if(this._y > ymax) {this._y = ymax;} else if(this._y < ymin) {this._y = ymin;}
}
 
for(var i = 0; i < n; i++) {
var cercle = this.attachMovie("cercle", "cercle"+i, i + 1);
cercle._height = cercle._width = 5;
cercle.a = amin + i*(amax - amin)/(n - 1);
cercle.onEnterFrame = deplacement;
}
 
 
Commentaires du code n°4
 
Ces 4 paramètres définissent les abscisses et les ordonnées minimales et maximales entre lesquelles devront évoluer les différents cercles. La zone définie est donc rectangulaire.
xmin = 20;
ymin = 20;
xmax = 380;
ymax = 180;
 
Ce paramètre représente le nombre de cercles qui devront suivre le déplacement de la souris.
n = 10;
 
Ces deux paramètres sont les bornes des coefficients multiplicateurs qui permettront de définir la vitesse de déplacement de chaque cercle.
amin = 0.05;
amax = 0.5;
 
On crée un clip vide dans lequel on trace un rectangle qui correspond à la zone dans laquelle les cercles sont "emprisonnés".
this.createEmptyMovieClip("rectangle_mc", 0);
with(rectangle_mc) {
lineStyle(0, 0x000000, 100);
moveTo(xmin, ymin);
lineTo(xmax, ymin);
lineTo(xmax, ymax);
lineTo(xmin, ymax);
lineTo(xmin, ymin);
}
 
On crée une fonction qui permettra de gérer le déplacement de chaque cercle. Cette fonction devrait vous être familière ! Les deux dernières lignes de cette fonction permettent de s'assurer que les abscisses restent comprises entre xmin et xmax et que les ordonnées restent comprises entre ymin et ymax.
function deplacement () {
var dx = _xmouse - this._x;
var dy = _ymouse - this._y;
this._x += this.a*dx;
this._y += this.a*dy;
if(this._x > xmax) {this._x = xmax;} else if(this._x < xmin) {this._x = xmin;}
if(this._y > ymax) {this._y = ymax;} else if(this._y < ymin) {this._y = ymin;}
}
 
On utilise une boucle for indexée sur la variable i.
for(var i = 0; i < n; i++) {
 
On cherche dans la bibliothèque, le clip dont le nom de liaison est "cercle" et on place sur la scène principale des occurrences de ce cercle qui portent les noms cercle0, cercle1, cercle2,...
var cercle = this.attachMovie("cercle", "cercle"+i, i + 1);
 
On définit les dimensions de chaque cercle.
cercle._height = cercle._width = 5;
 
On définit le coefficient multiplicateur de chaque cercle : pour le premier cercle ce coefficient sera égal à amin tandis que pour le dernier cercle ce coefficient sera égal à amax... Le premier cercle sera donc le plus lent tandis que le dernier cercle placé dans cette boucle sera le plus rapide.
cercle.a = amin + i*(amax - amin)/(n - 1);
 
Chaque cercle placé sur la scène fera appel à chaque image à la fonction deplacement définie plus haut.
cercle.onEnterFrame = deplacement;
 
fin de la boucle for.
}
 
Une dernière remarque
 

La technique que je viens de vous expliquer est utilisée dans ce tutoriel avec les propriétés _x et _y d'un clip mais elle peut être utilisée pour d'autres propriétés comme _alpha ou _rotation... Le principe est toujours le même : vous voulez faire tendre la valeur d'une propriété vers une valeur cible, il suffit alors de procéder de la manière suivante.

coefficient = 0.2;

onEnterFrame = function() {
var différence = valeurCible - valeurActuelle;
valeurActuelle += coefficient*différence;
}

 

Plus la valeur du coefficient est proche de 1, plus la convergence vers la valeur cible est rapide. Si la valeur du coefficient est proche de 0 cette convergence est lente.

Une petite illustration de cette dernière remarque par une animation qui utilise la technique du easing pour faire tourner des clips.