Lorsque l'on fait des animations, on doit souvent prévoir des comportement qui semblent physiquement acceptables :
Nous allons suivre ici l'exemple d'une bille qui rebondit.
Dans un premier temps, nous n'utiliserons pas de classe. Dans un deuxième temps nous ajouterons une classe pour permettre l'étape suivante : beaucoup de billes qui rebondissent.
Notre bille sera un cercle d'un certain diamètre taille d, une certaine position x, y. À chaque instant la bille tombera verticalement avec une vitesse vy. L'accélération de la pesanteur g modifiera la valeur de vy. Enfin, la bille rebondira sur la ligne du bas de la fenêtre mais en perdant un peu de vitesse. On notera r le facteur de proportionnalité entre la vitesse avant le choc et la vitesse après le choc. On a bien sûr 0 < r <= 1.
y grandit vers le bas. Le sol est atteint quand on touche le bord inférieur de la fenêtre. On peut connaître la hauteur de la fenêtre grâce au mot-clé height. Idem pour la largeur avec width.g la valeur physique de $9,81\,m\cdot s^{-2}$ car il faudrait alors faire une conversion prenant en compte l'unité de longueur sur l'écran et l'unité de temps de l'animation. Même si on mène ces calculs à bien, il n'est pas évident que l'animation en soit plus satisfaisante. Il est bien plus efficace de choisir, après quelques essais, la valeur qui produit l'animation la plus esthétique.
Si y > height, cela signifie que la bille a dépassé le bord du bas et qu'elle doit donc rebondir.
depassement = y - height. Ce parcours aurait dû être fait dans l'autre sens, vers le haut. Donc on peut calculer y = height - depassement. On peut tenir compte de la perte d'énergie et donc y = height - r*depassement.vy est renversée mais avec une atténuation : vy = -r*vy.
final float g = 0.05;
final float r = 0.8;
int d; // diamètre bille
float x, y, vy;
void setup() {
size(600, 400);
x = 300;
y = 10;
vy = 0;
d = 5;
}
void draw() {
background(250); // en niveau de gris
vy += g;
y += vy;
if (y > height) {
// rebond
float depassement = y - height;
y = height - r*depassement;
vy = -r*vy;
}
circle(x, y, d);
}
On peut confier la physique à la bille elle-même ce qui permettra de multiplier les billes sans alourdir le code.
final float g = 0.05;
final float r = 0.8;
Bille b;
void setup() {
size(600, 400);
b = new Bille(300, 10, 5);
}
void draw() {
background(250); // en niveau de gris
b.update();
b.display();
}
class Bille {
float x, y, vy, d;
Bille(float x0, float y0, float d0) {
d = d0;
x = x0;
y = y0;
vy = 0;
}
void update() {
vy += g;
y += vy;
if (y > height) {
// rebond
float depassement = y - height;
y = height - r*depassement;
vy = -r*vy;
}
}
void display() {
circle(x, y, d);
}
}