Solution du TD Vol d'une nuée d'oiseaux.
radians permet de convertir un angle en degré vers un angle en radians. Dans Processing, les fonctions trigonométriques sont en radians, mais il est souvent plus facile de raisonner en degrés. La fonction radians permet de faire simplement la conversion.
final int N = 200; // nombre total d'oiseaux
final int V = 2; // vitesse de chaque oiseau
final int Rmax = 30; // rayon pour le voisinage
final float s = 0.3; // coefficient pour adoucir l'alignement
Bird[] birds = new Bird[N]; // ensemble des oiseaux
void setup() {
size(800,600);
fill(255);
stroke(255);
for (int i=0; i<N; i++){
birds[i] = new Bird();
}
}
void draw(){
background(100,100,200);
for (int i=0; i<N; i++){
birds[i].align(birds);
}
for (int i=0; i<N; i++){
birds[i].update();
birds[i].display();
}
}
class Bird {
/* classe décrivant un oiseau */
float x, y, angle;
Bird() {
/* un oiseau est initialisé aléatoirement sur la fenêtre */
x = random(width);
y = random(width);
angle = random(360);
}
void display() {
/* l'oiseau est un simple cercle avec un trait
pour donner l'orientation
*/
circle(x, y, 5);
float dx = 10*cos(radians(angle));
float dy = 10*sin(radians(angle));
line(x,y,x+dx,y+dy);
}
void update() {
/* met à jour la position de l'oiseau
tenant compte de sa vitesse
si l'oiseau dépasse d'un bord,
il réapparaît à l'opposé
*/
float vx = V*cos(radians(angle));
float vy = V*sin(radians(angle));
x += vx;
if (x<0) {
x = x + width;
} else if (x > width) {
x = x - width;
}
y += vy;
if (y<0) {
y = y + height;
} else if (y > height) {
y = y - height;
}
}
float d2(Bird b){
/* renvoie la distance**2 de self
avec l'oiseau b
*/
return (x - b.x)*(x - b.x) + (y - b.y)*(y-b.y);
}
float ecartAngle(Bird b) {
/* mesure l'écart d'angle sentre self et l'oiseau b
renvoie le résultat entre -180 et 180 degrés
*/
float ecart = b.angle - angle;
if (ecart > 180) {
return ecart -360;
} else if (ecart <= -180) {
return ecart + 360;
} else {
return ecart;
}
}
void align(Bird[] birds){
/* parmi l'ensemble des oiseaux birds,
cherche les oiseaux qui sont dans le voisinage
pour chacun d'eux cumule l'écart d'angle afin
de calculer la moyenne,
puis modifie self.angle pour aligner self avec ses voisins
*/
float a = 0;
int n = 0;
for (int i=0; i<N; i++){
Bird b = birds[i];
if (d2(b)<Rmax*Rmax) {
a += ecartAngle(b);
n++;
}
}
float moy = a/n;
angle = angle + s*moy;
}
}