Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
atelier:processing:start [2023/01/06 15:01]
gweltaz
atelier:processing:start [2023/03/02 23:39] (Version actuelle)
gweltaz
Ligne 240: Ligne 240:
  
 <code java> <code java>
 +
 import peasy.*; ​ // On importe la librairie peasyCam import peasy.*; ​ // On importe la librairie peasyCam
  
Ligne 268: Ligne 269:
 } }
 </​code>​ </​code>​
 +
 +==== Forme ultime ====
 +
 +Voilà ce que ça peut donner, avec une bonne dose <​del>​d'​obstination</​del>​ de //​persévérance//​ et de <​del>​caféine</​del>​ //​trigonométrie//​.
 +
 +Le texte pour l'​étiquette a été fait avec **Inkscape** (le fichier, nommé "​label.png",​ doit être placé dans le répertoire du sketch).
 +
 +{{ :​atelier:​processing:​vinyle_processing.png?​nolink |}}
 +
 +<code java>
 +import peasy.*;
 +
 +PeasyCam cam;
 +
 +float LABEL_RADIUS = 130.0f;
 +float RECORD_RADIUS = 400f;
 +PVector p1 = new PVector();
 +PVector p2 = new PVector();
 +float rec_rot = 0.0f;
 +float rot_speed = 0.02f;
 +PImage label;
 +
 +
 +void setup() {
 +  size(500, 500, P3D);
 +  //​fullScreen(P3D);​
 +  hint(DISABLE_DEPTH_TEST); ​ // Pour éviter les problèmes de superposition lorsqu'​on dessine plusieurs objets sur le même plan en 3D
 +  cam = new PeasyCam(this,​ 400);
 +  label = loadImage("​label.png"​);​
 +}
 +
 +void draw() {
 +  background(255);​
 +
 +  // Dessiner les sillons du vinyle
 +  fill(0);
 +  noStroke();
 +  circle(0, 0, 2 * RECORD_RADIUS);​
 +  strokeWeight(1.4);​
 +  float angle = rec_rot;
 +  float radius = LABEL_RADIUS;​
 +  while (radius < LABEL_RADIUS + 34) {
 +    p1.set(radius * cos(angle), radius * sin(angle));​
 +    angle += 0.05f;
 +    radius += 0.14f;
 +    p2.set(radius * cos(angle), radius * sin(angle));​
 +    float seg_angle = 1.02 * sin(2 * atan2(p2.y-p1.y,​ p2.x-p1.x));​
 +    seg_angle *= seg_angle * seg_angle;
 +    seg_angle += 0.5 * sin(2 * atan2(p2.y-p1.y,​ p2.x-p1.x) + PI);
 +    seg_angle += random(0.2f);​
 +    seg_angle *= 230;
 +    stroke(seg_angle * 0.8, seg_angle*0.8,​ seg_angle);
 +    line(p1.x, p1.y, p2.x, p2.y);
 +  }
 +  while (radius < RECORD_RADIUS - 14) {
 +    p1.set(radius * cos(angle), radius * sin(angle));​
 +    angle += 0.03f;
 +    radius += 0.005f;
 +    p2.set(radius * cos(angle), radius * sin(angle));​
 +    float seg_angle = 1.02 * sin(2 * atan2(p2.y-p1.y,​ p2.x-p1.x));​
 +    seg_angle *= seg_angle * seg_angle;
 +    seg_angle *= seg_angle * seg_angle;
 +    seg_angle += 0.5 * sin(2 * atan2(p2.y-p1.y,​ p2.x-p1.x) + PI);
 +    seg_angle += random(0.1f);​
 +    seg_angle *= 230;
 +    stroke(seg_angle * 0.8, seg_angle*0.8,​ seg_angle);
 +    line(p1.x, p1.y, p2.x, p2.y);
 +  }
 +
 +  // L'​étiquette centrale
 +  noStroke();
 +  fill(255, 255, 0);
 +  circle(0, 0, LABEL_RADIUS * 2);
 +  rotate(rec_rot);​
 +  image(label,​ -label.width*0.5,​ -label.height*0.5);​
 +  // Le trou central
 +  fill(255);
 +  circle(0, 0, 20);
 +  ​
 +  rec_rot += rot_speed;
 +  if (rec_rot > TWO_PI) {
 +    rec_rot -= TWO_PI;
 +  }
 +}
 +</​code>​
 +
 +{{ :​atelier:​processing:​vinyle_label.png?​nolink |}}
 +
 +
 +===== Sketch 05 : Étoile des neiges... =====
 +
 +Encore un truc de saison, saupoudré de kitshitude, avec cette ode à l'​hiver : nous allons faire tomber de flocons. Une façon d'​aborder les particules et de s'​émerveiller devant son écran.
 +
 +On commence par trouver une belle image de flocon sur internet (je ne sais plus d'où je l'ai sorties donc excusez l'​absence de source et de licence...)
 +
 +La seconde image a été dérivée de la première en y appliquant un **flou gaussien** dans le logiciel **Gimp**.
 +
 +{{:​atelier:​processing:​snowflake_400.png?​nolink |}}
 +
 +{{:​atelier:​processing:​snowflake_flou.png?​nolink|}}
 +
 +<code java>
 +PImage fl_flou;
 +PImage fl_moyen;
 +PImage fl_petit;
 +
 +ArrayList<​PVector>​ flocons_pos = new ArrayList(); ​ // Liste qui contiendra la position de chaque flocon
 +ArrayList<​PImage>​ flocons_img = new ArrayList(); ​  // Liste qui contiendra l'​image de chaque flocon
 +
 +
 +void setup() {
 +  size(800, 600);
 +  ​
 +  fl_flou = loadImage("​snowflake_flou.png"​);​
 +  fl_moyen = loadImage("​snowflake_400.png"​);​
 +  fl_moyen.resize(100,​ 0);     // On redimensionne l'​image à 100 pixels de largeur,
 +  fl_petit = fl_moyen.copy();​
 +  fl_petit.resize(50,​ 0);      // le second argument '​0'​ permet de garder la même proportion pour la hauteur
 +  ​
 +  for (int i=0; i<30; i++) {   // On crée 30 petits flocons
 +    flocons_img.add(fl_petit);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +  for (int i=0; i<10; i++) {   // 10 flocons moyens
 +    flocons_img.add(fl_moyen);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +  for (int i=0; i<4; i++) {    // et 4 gros flocons
 +    flocons_img.add(fl_flou);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +}
 +
 +
 +void draw() {
 +  background(255);​
 +  ​
 +  for (int i=0; i<​flocons_img.size();​ i++) {
 +    PImage img = flocons_img.get(i);​
 +    PVector pos = flocons_pos.get(i);​
 +    pos.y += img.width * 0.01;      // Le floncon tombe à une vitesse proportionelle à sa taille
 +    pos.x += random(-1, 1);
 +    pos.y += random(-1, 1);
 +    pos.z += random(0, 1) * 0.1;    // Rotation du flocon
 +    if (pos.y > height + img.height/​2) {
 +      pos.y = -img.height/​2; ​       // On replace le flocon au dessus de la fenêtre
 +      pos.x = random(width) - img.width/​2; ​ // Avec une position horizontale aléatoire
 +    }
 +    // Les instructions suivantes permettent de faire une rotation et une translation du flocon
 +    push();
 +    translate(pos.x,​ pos.y);
 +    rotate(pos.z);​
 +    image(img, -img.width*0.5,​ -img.height*0.5);​
 +    pop();
 +  }
 +}
 +</​code>​
 +
 +==== Seconde forme : Vitesse et accélération ====
 +
 +Pour le moment l'​animation des flocons est saccadée puisque qu'ils sautent d'une position à une autre (à une distance aléatoire). Ça donne un effet stop-motion assez sympa, mais si on veut avoir des mouvements plus naturels il va falloir procéder d'une autre façon : en utilisant un variable de vitesse.
 +
 +<code java>
 +PImage fl_flou;
 +PImage fl_moyen;
 +PImage fl_petit;
 +
 +ArrayList<​PVector>​ flocons_pos = new ArrayList();​
 +ArrayList<​PImage>​ flocons_img = new ArrayList();​
 +ArrayList<​PVector>​ flocons_vel = new ArrayList(); ​ // Liste qui contiendra la vitesse (linéaire et angulaire) de chaque flocon
 +
 +
 +void setup() {
 +  size(500, 500);
 +  ​
 +  fl_flou = loadImage("​snowflake_flou.png"​);​
 +  fl_moyen = loadImage("​snowflake_400.png"​);​
 +  fl_moyen.resize(100,​ 0);
 +  fl_petit = fl_moyen.copy();​
 +  fl_petit.resize(50,​ 0);
 +  for (int i=0; i<30; i++) {
 +    flocons_img.add(fl_petit);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +  for (int i=0; i<10; i++) {
 +    flocons_img.add(fl_moyen);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +  for (int i=0; i<4; i++) {
 +    flocons_img.add(fl_flou);​
 +    flocons_pos.add(new PVector(random(width),​ random(height)));​
 +  }
 +  ​
 +  // Donne une vitesse aléatoire (la troisième valeur étant la vitesse de rotation) à chaque flocon
 +  for (int i=0; i<​flocons_img.size();​ i++) {
 +    flocons_vel.add(new PVector( random(-1, 1) * 0.01, random(-1, 1) * 0.01, random(-1, 1) * 0.1 ));
 +  }
 +}
 +
 +
 +void draw() {
 +  background(255);​
 +  ​
 +  for (int i=0; i<​flocons_img.size();​ i++) {
 +    PImage img = flocons_img.get(i);​
 +    PVector pos = flocons_pos.get(i);​
 +    PVector vel = flocons_vel.get(i); ​ // On récupère la vitesse de ce flocon
 +    ​
 +    // On ajoute une accélération aléatoire à la vitesse
 +    vel.x += random(-1, 1) * 0.004;
 +    vel.y += random(-1, 1) * 0.002;
 +    vel.z += random(-1, 1) * 0.001;
 +    ​
 +    pos.y += img.width * (vel.y + 0.04); ​ // La position augmente en fonction de la vitesse
 +    pos.x += vel.x;
 +    pos.z += vel.z;
 +    if (pos.y > height + img.height/​2) {
 +      pos.y = -img.height/​2;​
 +      pos.x = random(width) - img.width/​2;​
 +      vel.y = 0;
 +    }
 +    // Les instructions suivantes permettent de faire une rotation et une translation du flocon
 +    push();
 +    translate(pos.x,​ pos.y);
 +    rotate(pos.z);​
 +    image(img, -img.width*0.5,​ -img.height*0.5);​
 +    pop();
 +  }
 +}
 +</​code>​
 +
 +{{ :​atelier:​processing:​flocons_processing.gif?​nolink |}}
 +
 +
 +===== Sketch 06 : Pluie =====
 +
 +On continue de suivre le fil des saisons avec une idée proposée par Martin et inspirée par un sketch, [[http://​www.polguezennec.fr/​archive/​12_impluvium/​index.html|Impluvium]] de Pol Guezennec.
 +
 +La particularité de cet exercice (et sa complexité) tient dans le fait qu'il y a deux états à l'​animation : le premier lorsque la goutte tombe verticalement,​ le second lorsque 3 ondes croissent jusqu'​à atteindre chacun leur taille maximale.
 +
 +Puisqu'​il n'y a que ces deux états on pourra utiliser une variable ''​etat''​ de type ''​boolean''​ (valeur binaire ''​true''​ ou ''​false''​) pour définir l'​état actuel de notre euh... élément aqueux.
 +
 +L' ''​etat''​ passera de ''​false''​ (goutte tombante) à ''​true''​ (onde croissante) lorsque la goutte sera tombée d'une hauteur supérieure à la composante ''​y''​ de la variable ''​pg''​. ''​pg''​ est un //vecteur// à deux composantes (''​x''​ et ''​y''​) qui définit à la fois le point de départ (sur l'axe horizontal) et le point d'​arrivée (sur l'axe vertical) de notre goutte. Les valeurs de ''​pg''​ seront réinitialisées au hasard à chaque nouveau cycle pour ajouter un peu de variété à l'​animation.
 +
 +L'​illusion n'est pas parfaite car la goutte disparaît instantanément après impact pour laisser place aux ondes. Si on était soucieux du réalisme on tronquerait progressivement la partie inférieur de la goutte qui est au-delà du point d'​impact mais bon... L'​animation est suffisamment rapide pour qu'on y voit que du feu !
 +
 +{{ :​atelier:​processing:​goutte_01.gif?​nolink |}}
 +
 +<code java>
 +// Variables de l'​état "​goutte"​
 +float vitesse_goutte = 30;  // Vitesse verticale (en pixel/​frame)
 +float taille_goutte = 70;
 +float inclinaison = 20;     // Décallage horizontal (en pixels) entre le haut et le bas de la goutte
 +PVector pg = new PVector(random(500),​ 370);  // Contient la coordonnée horizontale de la goutte (x)
 +                                              // Et la coordonnée verticale du point d'​impact final (y)
 +PVector p1 = new PVector(pg.x,​ -taille_goutte); ​ // Point supérieur de la goutte
 +PVector p2 = new PVector(pg.x + inclinaison,​ 0); // Point inférieur de la goutte
 +
 +// Variables de l'​état "​onde"​
 +float vitesse_onde = 3;     // Vitesse de croissance des ondes (en pixel/​frame)
 +float decalage_onde = 40;   // Décallage entre chaque onde (en pixels)
 +float taille = 0.0;         // Taille de la première onde, à chaque instant
 +float taille2 = -1 * decalage_onde; ​ // Taille de la deuxième onde, à chaque instant
 +float taille3 = -2 * decalage_onde; ​ // Taille de la troisième onde, à chaque instant
 +float taille_max = 150;
 +float ratio = 2.5;          // Ratio entre la largeur et la hauteur de l'onde
 +
 +boolean etat = false; ​     // État goutte si "true, état onde si "​false"​
 +
 +
 +void setup() {
 +  size(500, 500);
 +  stroke(#​9D62FF);​
 +  strokeWeight(2);​
 +  noFill();
 +}
 +
 +void draw() {
 +  background(255);​
 +
 +  if (etat == false) {
 +    // Goutte d'eau
 +    p1.y += vitesse_goutte; ​     // La goutte descend (verticalement)
 +    p2.y += vitesse_goutte;​
 +    p1.x += vitesse_goutte * inclinaison / taille_goutte; ​ // La goutte se décalle en fct de son inclinaison
 +    p2.x += vitesse_goutte * inclinaison / taille_goutte;​
 +    line(p1.x, p1.y, p2.x, p2.y);
 +
 +    if (p2.y > pg.y) {
 +      etat = true;
 +      pg.x = p2.x;
 +    }
 +  } else {
 +    // Ondes
 +    taille = taille + vitesse_onde;​
 +    taille2 = taille2 + vitesse_onde;​
 +    taille3 = taille3 + vitesse_onde;​
 +
 +    if (taille > 0 && taille < taille_max)
 +      ellipse(pg.x,​ pg.y, ratio * taille, taille);
 +    if (taille2 > 0  && taille2 < taille_max)
 +      ellipse(pg.x,​ pg.y, ratio * taille2, taille2);
 +    if (taille3 > 0)
 +      ellipse(pg.x,​ pg.y, ratio * taille3, taille3);
 +
 +    if (taille3 > taille_max) {
 +      taille = 0.0;
 +      taille2 = -1 * decalage_onde;​
 +      taille3 = -2 * decalage_onde;​
 +      etat = false;
 +      pg = new PVector(random(0,​ 500), random(200, 400));
 +      p1 = new PVector(pg.x,​ -taille_goutte);​
 +      p2 = new PVector(pg.x + inclinaison,​ 0);
 +    }
 +  }
 +}
 +</​code>​
 +
  
  • atelier/processing/start.1673013702.txt.gz
  • Dernière modification: 2023/01/06 15:01
  • par gweltaz