Expressions/Aléatoire/Nombre aléatoire

La méthode random() permet de générer des valeurs aléatoires. À la différence de la méthode wiggle() qui génère au cours du temps des valeurs ayant une certaine continuité, la méthode random() produit à chaque image de l'animation une valeur aléatoire comprise dans un intervalle défini, sans tenir compte de la valeur générée à l'image précédente. Voici quelques exemples de sa syntaxe

random(); // entre 0 et 1
random(100); // entre 0 et 100
random(-50,50); // entre -50 et 50
random([20,20,-40],[50,50,100]); // entre [20,20,-40] et [50,50,100]
random([1,1,1,1]); // entre [0,0,0,0] et [1,1,1,1]

Pour visualiser ce que cela peut donner en terme d'animation, on écrit l'expression suivante sur la position d'un calque

random([width/2,height/2],[thisComp.width-width/2,thisComp.height-height/2]);

thisComp.width et thisComp.height désignent respectivement la largeur et la hauteur de la composition, alors que width et height désignent la largeur et la hauteur du calque. On attribue donc au calque une position aléatoire mais toujours comprise dans les limites de la composition (le calque ne dépasse jamais). On obtient quelque chose comme cela

seedRandom()

On constate dans l'animation précédente qu'à chaque image le calque est repositionné de façon aléatoire. Ceci peut être désiré mais parfois on aimerait éviter ce côté frénétique. After Effects met à disposition une méthode permettant d'avoir un certain contrôle sur les valeurs produites par random(). Cette méthode est appelée seedRandom(). Son fonctionnement n'est pas forcément facile à appréhender. La méthode random() génère une séquence de nombres aléatoires, un nombre à la première image, un autre nombre à la deuxième image, etc. Cette séquence est toujours différente, une même expression random() sur deux calques distincts par exemple donnera des valeurs différentes pour chacun. La méthode seedRandom() prend en considération deux arguments, le premier est appelé la "seed" (graine, en français) et sera un nombre; le deuxième argument peut être true ou false. On utilise la méthode seedRandom() avant d'appeler la méthode random(). Si l'on reprend l'exemple précédent en écrivant cette fois

seedRandom(5,true);
random([width/2,height/2],[thisComp.width-width/2,thisComp.height-height/2]);

on a maintenant un calque qui est positionné aléatoirement mais uniquement lors de la première image, ensuite il conserve la même position. Le fait d'avoir spécifier true pour le second argument indique à la méthode random() que l'on ne souhaite pas que le résultat dépende du temps, et donc qu'on aimerait avoir une valeur aléatoire mais la même à chaque image. Modifier la valeur de la seed aura pour influence de changer la séquence de nombres générée par random(). À chaque valeur de la seed correspond une séquence de nombres. Si l'on écrit une expression dans laquelle on a une seed égale à 1 et que l'on fait ensuite appel quatre fois de suite à la méthode random(), alors cette dernière génèrerait par exemple 2, 3, 4, 5; si l'on modifie la seed, en lui attribuant une valeur de 2, random() va générer une séquence différente, disons 6, 7, 8, 9. Maintenant si l'on modifie à nouveau la valeur de la seed en lui redonnant la valeur de 1, la séquence 2, 3, 4, 5 va être générée à nouveau. On a ainsi un certain contrôle, notamment pour récupérer des informations du passé (malheureusement en les recalculant à chaque fois). Avec seedRandom() , on va aussi pouvoir attribuer une position aléatoire à un calque, non pas à chaque image mais à chaque intervalle de temps qu'on aura spécifié. Dans l'expression de position suivante

duree = 0.5; // durée de l'intervalle en seconde
i = Math.floor(time / duree);
seedRandom(i,true);
random([width/2,height/2],[thisComp.width-width/2,thisComp.height-height/2]);

la première instruction définit la durée entre deux repositionnements du calque, ici toutes les 0.5 secondes, le calque va changer aléatoirement de position; la fonction Math.floor() calcule la partie entière d'un nombre, en arrondissant vers le bas (par exemple Math.floor(2.7) = 2); la variable i va ainsi augmenter d'une unité toutes les 0.5 secondes et par conséquent toutes les 0.5 secondes, la valeur de la seed change (la seed est représentée par i dans l'exemple); finalement random() produira une nouvelle position aléatoire toutes les 0.5 secondes. La nouvelle animation est celle-ci

On aurait pu pour réaliser la même animation, utiliser posterizeTime(), qui permet au sein d'une expression d'avoir une cadence différente de celle de la composition (une cadence inférieure par exemple). Le paramètre à préciser correspond à la cadence souhaitée en nombre d'images par seconde. On aurait obtenu le même résultat avec une expression ressemblant à celle-ci

posterizeTime(2);
random([width/2,height/2],[thisComp.width-width/2,thisComp.height-height/2]);

On va maintenant chercher à réaliser un tableau de lettres qui défile aléatoirement pendant un certain laps de temps, puis se fixe pendant un autre laps de temps. Les deux paramètres d'entrée sont la durée du défilement et la durée de l'immobilité. On commence par créer un calque texte dans une composition 320x240. Puisque l'on souhaite créer un tableau on pourra le dupliquer par la suite. Mais avant de le dupliquer on lui ajoute l'expression suivante sur la position pour que les calques dupliqués se placent automatiquement (en colonne).

dec = 25; // décalage entre 2 lignes, en pixel
[160,index * dec];

On écrit ensuite une expression sur la propriété "Décalage de caractères" (petit triangle "Animer" puis "Décalage de caractères"). C'est elle qui va produire l'effet recherché.

rd = 1.0; // durée affichage aléatoire, en seconde
fix = 0.5; // durée affichage fixe, en seconde
cycle = rd + fix;
reste = time % cycle;
if (reste < rd)
{
   random(26);
}
else
{
   0;
}

Pour l'expliquer on va considérer un cas en particulier, par exemple le moment où t = 2.8s. L'expression va calculer (la variable reste) 2.8 % 1.5 = 1.3, puis elle compare cette valeur avec rd, qui vaut 1.0. La valeur étant supérieure à rd le premier bloc d'instruction ne sera pas évalué, et par conséquent le décalage sera de 0 (texte fixe) pour t = 2.8s. En dupliquant le calque on obtient le tableau suivant (les lettres défilent pendant une seconde et se fixent pendant 0.5 secondes)

Et en guise de dernier exemple, qui ne sera pas expliqué ici (mais dont on peut trouver plusieurs commentaires et explications à partir de ce post sur le forum After Effects du Repaire), voilà une expression qui permet de déplacer un calque aléatoirement sur un damier, en se déplaçant de façon linéaire d'une case à une autre. Je remercie Bruno Quintin (aka Sequelles) pour avoir proposé cette expression

deplace = 1; // durée déplacement, en nb d'images
fixe = 1; // durée affichage fixe, en nb d'images
G = width;
D = thisComp.width - G;
H = height;
B = thisComp.height - H;
P1 = P2 = position;
dep = [0,0,0,0];
i = 0;

while (i < timeToFrames())
{
   seedRandom(i,true);
   P1 = P2;
   bor = [G <= P1[0],P1[0] <= D,H <= P1[1],P1[1] <= B];
   ale = Math.ceil(random(bor[0]+bor[1]+bor[2]+bor[3]));
   for (n = 0; n <= 3; n++)
   {
      dep[n] = bor[n] * (ale == 1);
      ale -= bor[n];
   }
   P2 += [((dep[0] == 0)-(dep[1] == 0)) * G,((dep[2] == 0)-(dep[3] == 0)) * H];
   i += deplace + fixe;
}
linear(timeToFrames(),i - deplace,i,P1,P2);

qui est illustrée ci-dessous