Comment faire une rotation d'image dans un tableau

Bonjour,
Je suis une étudiante en design et pour un projet je souhaitais réaliser un jardin numérique.
Je débute dans le milieu de processing et la base du code est faite en collaboration avec mon professeur de techno. Mon problème est que je me heurte actuellement à un soucis de rotation d’images.

Mon intention :
Je fais apparaitre autour de mon curseur des images de manière aléatoire car j’ai (6 images que j’ai renommé de 1 à 6). Maintenant je souhaiterais que toutes mes images tournent sur elles-même jusqu’a ce qu’elles disparaissent.
J’ai essayé pleins de petites choses dont un void spin, mais impossible de faire fonctionner.
Avez-vous des solutions à mon problème ?
Je vous remercie par avance !!
Justine :slight_smile:

int numberOfImages =6;
PImage images[] = new PImage[numberOfImages];
ArrayList<fleur> listeFleurs = new ArrayList<fleur>();
float deltaT_CreaImage = 300; // temps entre deux création de fleur
float top_Image = 0; // chronomètre
float deltaT_effaceImage = 1000; // temps entre deux création de fleur
float top_effaceImage = 0; // chronomètre
int a;
void setup() {
  
  size(800, 800);
  //background(0);  
  

  for (int i=1; i<=numberOfImages; i++) {
    //String nomImage = i + ".png";
    images[i-1] = loadImage(i + ".png");

  }

  for (PImage im : images) {
    int x = floor(random(100, width-100));
    int y = floor(random(100, height-100));
    listeFleurs.add(new fleur(im, x, y));

  }
}

void draw() {
  fill(0, 10);
  background(0);
  

  for (fleur f : listeFleurs) {
    f.affiche();

  }
  // ajout d'une nouvelle fleur dans la liste au dela de deltaT
  if (millis() - top_Image > deltaT_CreaImage) {
    //créer une nouvelle fleur
    int i = (int)random(0, numberOfImages);
    listeFleurs.add(new fleur(images[i], mouseX, mouseY));
    // mémoriser le temps
    top_Image = millis();
  

    
  }
  // effacement d'une fleur
  if (millis() - top_effaceImage > deltaT_effaceImage) {
    //effacer la fleur à l'indice 0
 
    listeFleurs.remove(0);
    // mémoriser le temps
    top_effaceImage = millis();
  }
  
  
  
}

void mousePressed() {
  int i = (int)random(0, numberOfImages);
  listeFleurs.add(new fleur(images[i], mouseX, mouseY));
}

//------------Paramètre des touches du clavier------------------------------------//
void keyPressed () {
  if (key == 'c') {
    saveFrame("justine8.jpg");
  }
}


ClassFleur

class fleur {
PImage im;
int x; // position x
int y; // position y
int w; // largeur
int h; // hauteur
float a ; // angle de rotation de l’image

fleur(PImage _im) {
im = _im;
x = mouseX;
y = mouseY;
w = 100;
h = 100;
a=0;

}
fleur(PImage _im, int _x, int _y) {
im = _im;
x = _x;
y = _y;
w = 100;
h = 100;
a=0;
}

void affiche() {
pushMatrix();
translate(width / 2, height / 2);
rotate(a * TWO_PI / 360);
image(im, x, y, w, h);
a += 1;
popMatrix();

}
}

Bonsoir Justine,

Pourrais-tu stp éditer et formater ton post précédent en sélectionnant ton code et en cliquant sur le bouton </> qui se trouve dans la barre au dessus de l’éditeur de texte. Merci :+1:

1 chose avant de répondre à ta question:
au début de ton draw() a la place de rect(0, 0, width, height); pour effacer la frame précédente, on utilise plutôt la fonction background(color).

As-tu bien compris le code fait avec ton professeur?
Tu as dans ta classe fleur un fonction affiche qui s’occupe déjà d’appliquer une rotation à ton image en fonction d’un angle a. Tout ce qui te reste à faire c’est de faire évoluer a avec le temps pour que ton image tourne.

1 Like

Bonsoir,
Merci de ton aide précieuse !
Alors oui j’ai compris globalement le code que mon professeur a réalisé.
J’ai modifié le fill en background ça paraissait évidement merci !
Et j’ai essayé aussi ton conseil dans la fonction affiche de la classe fleur mais j’arrive seulement à faire la rotation du tableau et non chaque image séparément.
// ps : j’ai actualisé mon code

Il me semble que tu es sur processing et pas sur p5.js, si tu peux corriger le tag stp.

Ce que je te conseil dans un cas comme celui-ci c’est de simplifier ton problème. Pour l’instant, tu as 6 images, un tableau de fleur qui évolue au cours du temps, des positions aléatoires, des évênements… Ca fait beaucoup de chose à gérer est comprendre.

Commence par faire simple: 1 seule image et une seule fleur dont tu connais la position. Par exemple comme ceci:

PImage img;
Fleur fleur;

void setup() {
  size(400, 400);
  background(0);  

  img = loadImage("1.png");
  fleur = new Fleur(img, 100, 100);
}

void draw() {
  background(0);
  fleur.a = PI / 4;
  fleur.affiche();
}

class Fleur {
  PImage im;
  int x, y;  // position 
  int w, h;  // dimension
  float a ;  // angle de rotation de l’image

  Fleur(PImage _im, int _x, int _y) {
    im = _im;
    x = _x;
    y = _y;
    w = 50;
    h = 50;
    a=0;
  }

  void affiche() {
    image(im, x, y, w, h);
  }
}

image

J’en ai profité pour mettre un F majuscule au nom de ta classe par convention.

Tout ce que fais ce code c’est dessiner indéfiniment une fleur (= img1) à la position (100, 100) sur l’écran.
Maintenant, on peut essayer de la faire tourner de 45°. On modifie la fonction affiche:

void affiche() {
    pushMatrix();
    rotate(a);
    image(im, x, y, w, h);
    popMatrix();
  }

Et on oublie pas de mettre à jour notre boucle pour faire tourner l’image:

void draw() {
  background(0);
  fleur.a = PI / 4;
  fleur.affiche();
}

image

Bon… ça tourne mais pas tellement comme on aimerait =/
La raison c’est que la fonction rotate() fait tourner l’ensemble du canvas mais à partir de son centre (0,0) qui est le coin en haut à gauche.
Comme ce qu’on fait c’est mettre une image à la position (100, 100) et qu’ensuite on fait tourner notre canvas, ça explique le résultat qu’on voit à l’écran.

Pour éviter ça, il faut donc qu’on place notre image au centre, qu’on la tourne de 45° et qu’ensuite on la place ou on veut. Et pour cela, on peut utiliser la fonction translate:

void affiche() {
    pushMatrix();
    translate(x, y);           // 4- On déplace notre image à la position souhaitée. /!\ C'est maintenant la position du centre qu'on indique puisqu'on a appliqué le point 2- 
    rotate(a);                 // 3- On applique la rotation
    translate(-w / 2, -h / 2); // 2- On déplace notre image en son centre 
    image(im, 0, 0, w, h);     // 1- On place notre image aux coordonnées (0, 0) /!\ c'est le coin supérieur gauche de l'image qui est positioné à (0, 0), pas son centre => On déplace l'image grâce à la fonction translate
    popMatrix();
  }

La façon dont j’aime pensé aux transformations, c’est de les appliquer du bas vers le haut. C’est plus logique pour nous de penser comme ça (d’où ma numérotation dans le code)

image

C’est bon, on se rapproche du but ! On sait maintenant faire tourner une Fleur. Par contre, il faut maintenant qu’on l’anime dans le temps.

Le problème avec ta première façon de faire (incrémenter a dans la fonction affiche) c’est que toutes les fleurs vont tourner à la même vitesse et surtout à partir du moment ou tu les affiches, tu vas les faire tourner. Peut-être que tu aimerais les afficher fixes pendant un certain temps et ensuite commencer à les faire tourner?

L’idée de base c’est que chaque fleur possède une vitesse de rotation et une nouvelle fonction pour les faire tourner.
Cette nouvelle fonction aura besoin de connaitre le temps écoulé par rapport à la dernière fois que la fleur ait été affichée pour savoir de combien de degrés la faire tourner.
La classe ressemblera donc à ça:

class Fleur {
  PImage im;
  float x, y;    // position 
  float w, h;    // dimension
  float a ;      // angle de rotation de l’image
  float vitRot;  // Vitesse de rotation en rad/seconde par exemple

  Fleur(PImage _im, int _x, int _y) {
    im = _im;
    x = _x;
    y = _y;
    w = 50;
    h = 50;
    a=0;
    vitRot = PI / 2;
  }
  
  void tourne(int tpsEcoule) {
    // A définir
  }

  void affiche() {
    pushMatrix();
    translate(x, y);           // 4- On déplace notre image à la position souhaitée. /!\ C'est maintenant la position du centre qu'on indique puisqu'on a appliqué le point 2- 
    rotate(a);                 // 3- On applique la rotation
    translate(-w / 2, -h / 2); // 2- On déplace notre image en son centre 
    image(im, 0, 0, w, h);     // 1- On place notre image aux coordonnées (0, 0) /!\ c'est le coin supérieur gauche de l'image qui est positioné à (0, 0), pas son centre => On déplace l'image grâce à la fonction translate
    popMatrix();
  }
}

On peut directement coder la fonction tourne. Le temps écoulé sera donné en milliseconde, on divise donc par 1000 pour avoir le temps en seconde et on multiplie par la vitesse pour obtenir l’angle de rotation:

void tourne(int tpsEcoule) {
  a = a + vitRot * ((float)tpsEcoule / 1000);
}

La dernière chose à faire et de connaitre le temps écoulé, pour ça il faudra 3 variables. Une pour stocker le temps au début de ta boucle, une autre pour stocker le temps entre écoulé entre 2 boucles et une autre pour mémoriser le temps de de la boucle précédente.

En pratique, ça ressemble à ça:

void draw() {
  tpsActuel = millis();
  tpsEcoule = dernierTps - tpsActuel;
  
  // Ici ton code pour modifier tes fleurs et dessiner sur ton canvas
  background(0);
  fleur.tourne(tpsEcoule);
  fleur.affiche();
  
  dernierTps = tpsActuel;
}

Pour exemple, voici un code complet qui reprend ce qu’on a vu avant. La fleur commence à tourner après le click souris:

PImage img;
Fleur fleur;
boolean tourner;
int tpsActuel, dernierTps, tpsEcoule;

void setup() {
  size(400, 400);
  background(0); 
  tourner = false;
  dernierTps = 0;
  tpsEcoule = 0;

  img = loadImage("1.png");
  fleur = new Fleur(img, 100, 100);
}

void draw() {
  tpsActuel = millis();
  tpsEcoule = dernierTps - tpsActuel;
  
  background(0);
  fleur.tourne(tpsEcoule);
  fleur.affiche();
  
  dernierTps = tpsActuel;
}

void mouseClicked() {
  tourner = true;
}

class Fleur {
  PImage im;
  float x, y;    // position 
  float w, h;    // dimension
  float a ;      // angle de rotation de l’image
  float vitRot;  // Vitesse de rotation en rad/seconde par exemple

  Fleur(PImage _im, int _x, int _y) {
    im = _im;
    x = _x;
    y = _y;
    w = 50;
    h = 50;
    a=0;
    vitRot = PI / 2;
  }
  
  void tourne(int tpsEcoule) {
    a = a + vitRot * ((float)tpsEcoule / 1000);
  }

  void affiche() {
    pushMatrix();
    translate(x, y);           // 4- On déplace notre image à la position souhaitée. /!\ C'est maintenant la position du centre qu'on indique puisqu'on a appliqué le point 2- 
    rotate(a);                 // 3- On applique la rotation
    translate(-w / 2, -h / 2); // 2- On déplace notre image en son centre 
    image(im, 0, 0, w, h);     // 1- On place notre image aux coordonnées (0, 0) /!\ c'est le coin supérieur gauche de l'image qui est positioné à (0, 0), pas son centre => On déplace l'image grâce à la fonction translate
    popMatrix();
  }
}

Maintenant à toi d’adapter ce code avec plusieurs images, plusieurs fleurs, des positions aléatoires, des vitesses de rotations différentes etc.

1 Like

Merci pour votre Aide !
J’ai réussi à faire tourner mes images séparément avec des tailles et des vitesses aléatoires grâce aux explications ! Un grand merci pour votre pédagogie !

int numberOfImages =6;
PImage images[] = new PImage[numberOfImages];
ArrayList<fleur> listeFleurs = new ArrayList<fleur>();
float deltaT_CreaImage = 300; // temps entre deux création de fleur
float top_Image = 0; // chronomètre
float deltaT_effaceImage = 1000; // temps entre deux création de fleur
float top_effaceImage = 0; // chronomètre
int a;
void setup() {
  
  size(800, 800);
  //background(0);  

  for (int i=1; i<=numberOfImages; i++) {
    //String nomImage = i + ".png";
    images[i-1] = loadImage(i + ".png");

  }

  for (PImage im : images) {
    int x = floor(random(100, width-100));
    int y = floor(random(100, height-100));
    listeFleurs.add(new fleur(im, x, y));

  }
}

void draw() {
  fill(0, 10);
  background(0);
  

  for (fleur f : listeFleurs) {
    f.affiche();

  }
  // ajout d'une nouvelle fleur dans la liste au dela de deltaT
  if (millis() - top_Image > deltaT_CreaImage) {
    //créer une nouvelle fleur
    int i = (int)random(0, numberOfImages);
    listeFleurs.add(new fleur(images[i], mouseX, mouseY));
    // mémoriser le temps
    top_Image = millis();
  

    
  }
  // effacement d'une fleur
  if (millis() - top_effaceImage > deltaT_effaceImage) {
    //effacer la fleur à l'indice 0
 
    listeFleurs.remove(0);
    // mémoriser le temps
    top_effaceImage = millis();
  }
  
  
  
}

void mousePressed() {
  int i = (int)random(0, numberOfImages);
  listeFleurs.add(new fleur(images[i], mouseX, mouseY));
}

//------------Paramètre des touches du clavier------------------------------------//
void keyPressed () {
  if (key == 'c') {
    saveFrame("justine8.jpg");
  }
}
 
class fleur {
  PImage im;
  int x; // position x
  int y; // position y
  int w; // largeur
  int h; // hauteur
  float a ; // angle de rotation de l'image

  fleur(PImage _im) {
    im = _im;
    x = mouseX;
    y = mouseY;
    w = 100;
    h = 100;
    a=0;

  }
  fleur(PImage _im, int _x, int _y) {
    im = _im;
    x = _x;
    y = _y;
    w = 100;
    h = 100;
    a=0;
    
}



  void affiche() {
    pushMatrix();
    translate(width / 2, height / 2);
    rotate(a * TWO_PI / 360);
    image(im, x, y, w, h);
    a += 1;
    popMatrix();
     }  
  }
2 Likes