Ars Robota — 2012-01-19 20:19:32

Salut à toutes et tous,

Je voudrais créer une instance d'une class B avec les coordonnées de la dernière instance d'une class A (pour info, les coordonnées en question sont présentées sous forme d'un PVector(_x, _y) et sont créées dans une méthode). Mon problème est que je ne sais pas comment récupérer, dans la méthode draw, une variable de la dernière instance d'un objet dans la première instance d'un autre objet.

Ci-joint mon code (peut-être pas très propre, j'ai bidouillé un exemple d'Emoc - désolé!)

ArrayList tendrils;
ArrayList pollens;
float ang = 0;

void setup() {
  size(400,400);
  frameRate(30);
  smooth();
  tendrils = new ArrayList();
  pollens=new ArrayList();
}

void draw() {
  background(255);
  ang += random(-20, 20);
  tendrils.add( new Tendril(width / 2, height / 2));
  pollens.add(new Pollen(width/2, height/2));//ici je veux récupérer les coordonnéess x et y...
  
  if (tendrils.size() > 100) {
    tendrils.remove(0);
  }
  if(pollens.size()>200) {
    pollens.remove(0);
  }
  
  for (int i = 0; i < tendrils.size(); i++) {
     Tendril t = (Tendril) tendrils.get(i);
     t.update(ang);
     t.ink();
  }
  for (int j=0;j<pollens.size();j++) {
    Pollen p=(Pollen) pollens.get(j);
    p.update(ang);
    p.ink();
  }
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;
  
  Tendril(float _x, float _y) {
    posT = new PVector(_x, _y);
  }
  
  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);//... créées ici, dans la dernière instance
    s+=0.5;
    sat+=3;
    brite+=1;
  }
  
  void ink() {
    colorMode(HSB);
    fill(col,sat,brite,aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    aleph-=3;
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;
  
  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  
  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }
  
  void ink() {
    noFill();
    stroke(0,255,0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
Ars Robota — 2012-01-19 21:11:40

Oups, j'allais oublier: merci beaucoup par avance!
Alex

Turboconnard — 2012-01-20 10:04:21

// pollens.add(new Pollen(width/2, height/2));//ici je veux récupérer les coordonnéess x et y

var lastPollen = pollens.get(pollens.size()-1);
pollens.add(new Pollen(lastPollen.posP.x,lastPollen.posP.y));

moi je ferrais ça pour créer un pollen à la place du dernier pollen créé

si c'est pour le tendrill tu peux faire comme ça :

var lasttendril = lasttendril.get(lasttendril.size()-1);
pollens.add(new Pollen(lasttendril.posP.x,lasttendril.posP.y));

EricRG — 2012-01-20 13:35:50

Bonjour,

Je n'ai pas regardé le détail de ton code mais, d'une façon générale, pour pouvoir agir sur la dernière instance crée d'une classe A, tu peux créer une variable de type A au début du programme et mettre à jour cette variable dans le constructeur de la classe A.
Comme ça, elle pointe toujours vers le dernier objet "A" crée.

Comme ça tu peux l'utiliser pour t'adresser aux méthodes de cette dernière instance.

Exemple :  (Remarque : ici, les objets crées deviennent candidats au ramasse-miettes au fur et à mesure !)

A objetA;

int n=0;

void setup() {
  size(300,300);
  frameRate(3);
}

void draw() {
  n++;
  new A(n);
  objetA.display();
}

class A {
  int nombre;
 
  A(int nb) {
    nombre=nb;
    objetA=this;
  }
 
  void display() {
    println(nombre);
  }
}

22_ — 2012-01-20 13:41:20

Effectivement, comme Turboconnard, je te conseille de gérer ça avec une liste ordonnée de tes objets...

[Les attributs de classe sont des variables partagées par toutes les instances d'une même classe, il faut utiliser le mot clé static pour en déclarer un :

exemple classique d'utilisation d'un attribut de classe, le nombre d'instance d'une classe

class MaClasse{
   static int nombreInstanceClasse = 0;

   public MaClasse(){
       nomrbeInstanceClasse++;
   }
}

]

22_ — 2012-01-20 13:46:21

Oui... la solution d'Eric est trop limpide pour que mon esprit tordue ait pu y penser... :)

Turboconnard — 2012-01-20 15:41:58

Je ne conseille pas du tout l'utilisation de variables static pour ce genre de code...

Effectivement la méthode de EricRG focntionne dans ce cas mais c'est pas très "Objet". Dans le cas de Ars Robota on a déjà des Arraylists avec les instances et c'est plus "Objet" de passer des coordonnées au constructeur plutôt que d'utiliser une variables static.
Ex : si on devait avoir deux fenetres distinctes dans l'appli avec les pollens... les positions ne seraient pas bonnes

22_ — 2012-01-20 16:12:34

"Je ne conseille pas du tout l'utilisation de variables static pour ce genre de code... "

On est d'accord... je mettais juste un exemple d'attributs de classe pour qu'Ars comprenne de quoi il en retournait quand il parlait de variables de classe.

Ars Robota — 2012-01-20 19:01:47

Waouh! Merci beaucoup les codelaborantins pour vos réponses, je vais jeter un coup d'oeil atentif à tout ça.
aR

Ars Robota — 2012-01-21 14:47:39

citation :

var lasttendril = lasttendril.get(lasttendril.size()-1);

@turboconnard: Ca m'a l'air intéressant mais je ne sais pas quel type de variable utiliser pour déclarer lasttendril... processing me renvoi une erreur si j'utilise var.

Une idée?

Merci beaucoup,
aR

Ars Robota — 2012-01-21 17:52:11

OK, j'ai réussi à insérer la suggestion de turboconnard tout en me débarrassant des messages d'erreur... seulement la première instance de ma class Pollen continue de suivre la première instance de la class Tendril...

ArrayList tendrils;
ArrayList pollens;
float ang = 0;

void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
  tendrils = new ArrayList();
  pollens=new ArrayList();
}

void draw() {
  background(255);
  ang += random(-20, 20);
  tendrils.add( new Tendril(width / 2, height / 2));
  Tendril lastTendril=(Tendril) tendrils.get(tendrils.size()-1);
  pollens.add(new Pollen(lastTendril.posT.x, lastTendril.posT.y));//ajouter un élément pollens

  if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
    tendrils.remove(0);//on enlève le premier élément tendrils
  }
  if (pollens.size()>200) {
    pollens.remove(0);
  }

  for (int i = 0; i < tendrils.size(); i++) {
    Tendril t = (Tendril) tendrils.get(i);
    t.update(ang);
    t.ink();
  }
  for (int j=0;j<pollens.size();j++) {
    Pollen p=(Pollen) pollens.get(j);
    p.update(ang);
    p.ink();
  }
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;

  Tendril(float _x, float _y) {//déclaration du PVector de position de Tendril
    posT = new PVector(_x, _y);
  }

  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);
    //s+=0.5*random(-1,3);
    s+=0.5;
    sat+=3;
    brite+=1;
  }

  void ink() {
    colorMode(HSB);
    fill(col, sat, brite, aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    aleph-=3;
    //aleph-=random(2,4);
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;

  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }

  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }

  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
Turboconnard — 2012-01-21 19:55:18

et faudrait qu'elle fasse quoi la premiere instance de pollen ?

(désolé pour le var, des habitudes d'autres langages)

cgiles — 2012-01-21 19:59:15

J'ai un peu retoucher ton code mais je sais pas si c'est ce que tu veux :
La fonction add ajoutes un dernier element a la liste, j'initie un element pollen, en prenant les valeurs x et y du premier element de tendril
J'ai un peux otimiser ton code, c'est aexpliquer dans les commentaires
En gros j'ai typer les classes, pour rendre le code plus simple, ajoutez une nouvelle initiation d'instance pour pollen, et changer ta façon de générer le mouvement aléatoire, en utilisant le noise, test tu verras ;)

//CGILES: typage des arraylist en java 1.5, super pratique
//CGILES: l'arraylist renverra directement des objet selon le type demandé
//CGILES: ci dessus une arraylist Pollen et une arraylist Tendril
ArrayList<Tendril> tendrils;
ArrayList<Pollen> pollens;
float ang = 0;
// CGILES : incrémenteur pour le noise
float j=random(0,1000);;

void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
  tendrils = new ArrayList();
  pollens=new ArrayList();
}

void draw() {
  background(255);
  //CGILES : au lieu d'utiliser un random , utilisation d'un noise
  //CGILES: le noise est aléatoire mais lisse : http://en.wikipedia.org/wiki/Perlin_noise
  ang += map(noise(j/50),0,1,-10,10);
  j++;
  tendrils.add( new Tendril(width / 2, height / 2));
  //CGILES:retrait de la création de lastTrendril), car l'arraylist est typée
 /* CGILES : utilisation du nouveau créateur d'instance, 
 et on prend les valeur x et y du premier tendril 
 pour les mettre dans  le dernier element de la liste pollens*/
  pollens.add(new Pollen(tendrils.get(0)));//ajouter un élément pollens

  if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
    tendrils.remove(0);//on enlève le premier élément tendrils
  }
  if (pollens.size()>200) {
    pollens.remove(0);
  }

  for (int i = 0; i < tendrils.size(); i++) {
    Tendril t = tendrils.get(i);
    t.update(ang);
    t.ink();
  }
  for (int j=0;j<pollens.size();j++) {
    Pollen p= pollens.get(j);
    p.update(ang);
    p.ink();
  }
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;

  Tendril(float _x, float _y) {//déclaration du PVector de position de Tendril
    posT = new PVector(_x, _y);
  }

  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);
    //s+=0.5*random(-1,3);
    s+=0.5;
    sat+=3;
    brite+=1;
  }

  void ink() {
    colorMode(HSB);
    fill(col, sat, brite, aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    aleph-=3;
    //aleph-=random(2,4);
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;

  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  //CGILES: nouveau instancieurs de classe,
 //CGILES : prenant directement un objet Trendil en paramètre
Pollen(Tendril lastTrendil){
   posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
}

  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }

  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
Ars Robota — 2012-01-21 20:01:10

Et bien la première instance de Pollen devrait apparaître aux mêmes coordonnées que la dernière instance de Tendril, puis partir vers le haut de la fenêtre (style évaporation).

Merci de ton aide.
aR

Ars Robota — 2012-01-22 17:26:08

@cgiles: Je n'avais pas vu ton post. C'est exactement ça, merci beaucoup de ton aide je suis en train d'étudier ça.

citation :

  //CGILES: nouveau instancieurs de classe, prenant directement un objet Trendil en paramètre
  Pollen(Tendril lastTrendil) {
    posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
  }

Je comprends mieux le fonctionnement des objets (grâce à tes commentaires). Il me semblait bien que ça devait donner quelque chose comme ça mais je ne savais pas comment créer une instance de Pollen correspondant à la première instance (et non pas la dernière comme je le pensais) de Tendril, ni où placer les lignes de code supplémentaires.

cgiles — 2012-01-22 23:40:11

le bout de code que j'ai modifié et qui a changé le comportement est celui ci :
pollens.add(new Pollen(tendrils.get(0)));
on prend le premier element de la liste trendrill ( donc la queue de l'objet ) comme référence pour le dernier élément de la liste pollen ( soit la tête ).

Quand tu trouves pas la solution a un problème, hésites pas a consulter les docs des fonctions utilisés, tu peux y trouver poruquoi ça ne marche pas.

Ars Robota — 2012-01-23 22:05:24

OK, ok... je comprends mieux... Et si, par exemple, je voulais qu'après être apparus à la position de la dernière instance les objets Pollen partent dans leur propre direction, où devrais-je placer le code pour modifier posP? directement dans draw() ou dans l'update de la class Pollen?

Merci de votre aide,
aR

Turboconnard — 2012-01-23 22:53:22

Si tu veux rester objet c'est à tes instances de se déplacer "seules" donc dans oui, dans l'update de Pollen.

cgiles — 2012-01-24 09:31:47

Et si tu veux allez plus loin dans l'objet, tu peux créer un objet Pollens, qui contiendra tes instances Pollen...

Ars Robota — 2012-01-24 10:23:37

citation :

tu peux créer un objet Pollens, qui contiendra tes instances Pollen...

Un objet qui contient des instances? Tu m'intéresses! Mais je ne vois pas trop ce que ça peut donner... Est-ce que je pourrais créer un objet qui ne contiendrait que certaines instances de mon objet Pollen (en fait, toutes les instances sauf la première créée, qui aurait les même coordonnées que la première instance de Tendril)?

Merci beaucoup à tous de votre aide,
aR

Turboconnard — 2012-01-24 11:14:26

Je pense que ce que veux dire cgiles (tu me dis si je me trompe) c'est qu'une classe "PollenManager" ou "Pollens" (peu importe) te permettrait de créer des Pollens facilement, où tu veux et peut être pour un autre projet.

Une des idée de l'objet est de supprimer les "liens forts" entre les classes. Aujourdh'ui ton projet fonctionne mais ta classe principale "connait" tous les pollens, ce qui n'est pas forcément intéressant car si tu voulais recréer un autre départ de pollens il faudrait que tu ais un autre tableau avec tous tes autres pollens, que tu les updates un après l'autre etc...
Si tu fais une classe "PollenManager" ou plutôt "PollenEmiter" qui gère ça pour toi, tu pourrais créer facilement plusieurs départs de pollen en faisant :

PollenEmiter p1 = new PollenEmiter(250,350); //départ de pollen en x250,y350
PollenEmiter p2 = new PollenEmiter(12,84);//départ de pollen en x12,y84

plus facile que de recréer un tableau, faire des boucles etc... et surtout bien plus lisible !

cgiles — 2012-01-24 12:49:39

Turboconnard explique mieux que je ne l'aurais fait. Et tu pourrais ajouter dans ton manager une fonction dédié uniquement a la première instance de ta liste

Ars Robota — 2012-01-24 22:18:56

D'aaaaacord!... En fait, le truc consisterait à créer une class avec une fonction dédiée à la création des instances (un équivalent à pollens.add) et une autre à la mise à jour des coordonnées (ce qui, si je ne me trompe pas, existe déjà avec update)?

Donc: une fonction qui crée les instances, une fonction qui met à jour la première instance et une dernière qui met à jour les autres, le tout appelé dans une boucle for à l'intérieur de draw. J'ai bon, m'sieur?

Turboconnard — 2012-01-25 11:43:04

Je crois que t'es pas mal !

cgiles — 2012-01-25 15:11:56

Et tu peux aller plus loin en créant deux méthode update uune pour le premier, une pour les  suivant, et les mettre dans ta fonction update principale. et tu peux directement faire ta boucle for dans l'update de pollenManager, ainsi ton code draw se résumera a la création d'un pollenManager, son update et son display.

Ars Robota — 2012-01-25 16:33:18

... Le problème va être de mettre tout ça en pratique et c'est loin d'être gagné! Si vous avez des suggestions je suis pas contre...

cgiles — 2012-01-25 16:53:41

Il suffit simplement de reporter dans une classe ce que tu fais actuellement en setup et draw.
Ensuite tu peux utiliser un algorythme :
//creer les listes
//intialisaer les listes
//modifier la première valeur
//copier les valeurs en suivant
//ect...

Ars Robota — 2012-01-25 17:12:10

Bon alors ceci est un premier modèle (volontairement sommaire et incomplet, histoire de résumer):

Pollen p1;
int nbr;

void setup() {
  p1=new Pollen(x, y);
  nbr=20;
}

void draw() {
  for(int i=0;i<nbr;i++) {
    p1.emitter(x, y);
    p1.update();
    p1.update();
    p1.ink();
  }
}

class Pollen {
  PVector posP;
  
  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  Pollen(Tendril lastTendril) {// superflue?
    posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
  }
  
  void emitter(float x, float y) {
    posP.set(lastTendril.posT.x, lastTendril.posT.y);// possible?
  }
  
  void update1() {
  }
  
  void update2() {
  }
  
  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}

Voyez-vous de grosses erreurs pour l'instant, ormis le fait que les fonctions update ne sont pas écrites?

Merci beaucoup.

cgiles — 2012-01-25 17:37:19

a rajouté a la fin de ton code , la classe pollenManager :

class PollenManager {
  ArrayList<Pollen> pollens;
  ArrayList<Tendril> tendrils;
  float ang;
  int j;

  PollenManager() {
    tendrils = new ArrayList();
    pollens=new ArrayList();
    ang=0;
    j=(int)random(0, 1000);
  }

  void update() {
    ang += map(noise(j/50), 0, 1, -10, 10);
    j++;
    tendrils.add( new Tendril(width / 2, height / 2));

    pollens.add(new Pollen(tendrils.get(0)));//ajouter un élément pollens

    if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
      tendrils.remove(0);//on enlève le premier élément tendrils
    }
    if (pollens.size()>200) {
      pollens.remove(0);
    }

    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).update(ang);
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).update(ang);
    }
  }
  void  display() {
    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).ink();
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).ink();
    }
  }
}

et voila a quoi peut ressembler ton code principal avec ça :

PollenManager pollenManager;
void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
 pollenManager=new PollenManager();
}

void draw() {
  background(255);
  pollenManager.update();
  pollenManager.display();
}
Ars Robota — 2012-01-25 18:05:10

Merci cgiles, je vais essayer ça mais processing me dit, à propos de p1, que "field Component.x is not visible"... et si je supprime les paramètres x et y, il me dit que Pollen n'est pas défini. J'ai beau ré-examiner le code de long en large, je ne vois pas de quoi il s'agit.

cgiles — 2012-01-25 21:14:12

Repart du code que j'avais posté sur la page précédente, c'est ce que j'ai fait pour avoir une base fonctionnel.

Ars Robota — 2012-01-25 21:17:41

Merci beaucoup de ton aide (et de ta patience!), je vois ça tout de suite.

Edit: OK, au temps pour moi je n'avais pas ajouté ton code dans le bon sketch (:/).
J'ai effectivement deux tendrils dont un avec un émetteur de pollen qui colle à ce que je cherche. Je vais nettoyer le code et décortiquer tout ça et je te ferais part de mes modifs perso.

Encore merci à toi et à turboconnard pour votre aide!

aR

Ars Robota — 2012-01-25 22:33:11

Alors je reviens avec mon code modifié. Le voici:

PollenManager pollenManager;// PollenManager appelera Tendril et Pollen
float ang = 0;
// CGILES : incrémenteur pour le noise
float j=random(0,1000);
float nValX, nValY, nScale=0.05, m=0.00, n=1.00;

void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
  pollenManager=new PollenManager();
}

void draw() {
  background(255);
  pollenManager.update();
  pollenManager.display();
  //CGILES : au lieu d'utiliser un random , utilisation d'un noise
  //CGILES: le noise est aléatoire mais lisse : http://en.wikipedia.org/wiki/Perlin_noise
  ang += map(noise(j/50),0,1,-10,10);
  j++;
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;

  Tendril(float _x, float _y) {//déclaration du PVector de position de Tendril
    posT = new PVector(_x, _y);
  }

  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);
    //s+=0.5*random(-1,3);
    s+=0.5;
    sat+=3;
    brite+=1;
  }

  void ink() {
    colorMode(HSB);
    fill(col, sat, brite, aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    //aleph-=2;
    aleph-=random(1,4);
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;

  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  //CGILES: nouveau instancieurs de classe, prenant directement un objet Trendil en paramètre
  Pollen(Tendril lastTrendil) {//instance d'objet Tendril avec pour nom lastTendril
    posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
  }

  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }
  
  void update2(float nValX, float nValY) {
    posP.set(posP.x + nValX, posP.y + nValY);
  }

  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
/* ****************************************************************** */
class PollenManager {
  //CGILES: typage des arraylist en java 1.5, super pratique
  //CGILES: l'arraylist renverra directement des objet selon le type demandé
  //CGILES: ci dessus une arraylist Pollen et une arraylist Tendril
  ArrayList<Pollen> pollens;
  ArrayList<Tendril> tendrils;
  float ang;
  int k;

  PollenManager() {
    tendrils = new ArrayList();
    pollens=new ArrayList();
    ang=0;
    k=(int)random(0, 1000);
  }

  void update() {
    ang += map(noise(k/50), 0, 1, -10, 10);
    k++;
    tendrils.add( new Tendril(width / 2, height / 2));
    //CGILES:retrait de la création de lastTrendril), car l'arraylist est typée
  /* CGILES : utilisation du nouveau créateur d'instance, 
  et on prend les valeur x et y du premier tendril 
  pour les mettre dans  le dernier element de la liste pollens*/
    pollens.add(new Pollen(tendrils.get(0)));//ajouter un élément pollens

    if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
      tendrils.remove(0);//on enlève le premier élément tendrils
    }
    if (pollens.size()>100) {
      pollens.remove(0);
    }

    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).update(ang);
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).update(ang);
    }
  }
  
  void update2() {
    for (int j=0;j<pollens.size()-1;j++) {
      nValX=noise((n+x[j])*nScale);
      nValY=noise((m+j)*nScale);
      pollens.get(j).update2(nValX, nValY);
    }
  }
  
  void  display() {
    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).ink();
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).ink();
    }
  }
}

Maintenant j'ai deux questions/problèmes:
  - quelle est la cause du message d'erreur relatif au nombre de paramètre dans update2?
  - comment sélectionner la première instance de l'arraylist pollens (dans pollens.get)?

Merci beaucoup,

aR

cgiles — 2012-01-26 07:35:54

Si c'est update si :
void update2() {
    for (int j=0;j<pollens.size()-1;j++) {
      nValX=noise((n+x[j])*nScale);
      nValY=noise((m+j)*nScale);
      pollens.get(j).update2(nValX, nValY);
    }
  }
je vois aucune liste nommé "x"
si c'est celui la :
void update2(float nValX, float nValY) {
    posP.set(posP.x + nValX, posP.y + nValY,0);
  }
c'est le fait qu'il manque un zero a la fin pour les z.

Pour avoir accès a ton premier membre, sois tu testes avec un if si i=0 dans un boucle, sinon hors boucle tu fais un pollens.get(0);

Ars Robota — 2012-01-26 22:17:53

citation :

si c'est celui la :
void update2(float nValX, float nValY) {
    posP.set(posP.x + nValX, posP.y + nValY,0);
  }
c'est le fait qu'il manque un zero a la fin pour les z

Exact, j'avais oublié ce petit zéro, merci de me le rappeler... Mais tu as également pointé le problème de ma liste x manquante.

Celle-ci vient d'un autre sketch que je voudrais mélanger avec le sketch présent. Initialement il s'agit d'une liste déclarée sous la forme float[] x=new float[nbr];
Je vais essayer de l'insérer en gardant cette forme là.

Merci,
aR

cgiles — 2012-01-27 10:06:24

Je te conseille fortement de ne pas utiliser de x ou y comme nom de variable, déja parce que processing s'en sert je crois, ensuite pour la lecture de ton code^^ mais xList posListX, ect...

Ars Robota — 2012-01-27 19:45:12

Merci du conseil, je corrige ça!
Je me suis rendu compte que j'avais oublié d'appeler ma fonction update2 dans draw()... Corrigé aussi.
A présent le résultat semble un peu plus "logique" mais je pense que je devrais déplacer ma boucle for dans la fonction update2 de Pollen...

PollenManager pollenManager;// PollenManager appelera Tendril et Pollen
float ang = 0;
// CGILES : incrémenteur pour le noise
float j=random(0,1000);
int nbr=50;// nombre d'instances de Pollen

void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
  pollenManager=new PollenManager();
}

void draw() {
  background(255);
  pollenManager.update();
  pollenManager.update2();
  pollenManager.display();
  //CGILES : au lieu d'utiliser un random , utilisation d'un noise
  //CGILES: le noise est aléatoire mais lisse : http://en.wikipedia.org/wiki/Perlin_noise
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;

  Tendril(float _x, float _y) {//déclaration du PVector de position de Tendril
    posT = new PVector(_x, _y);
  }

  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);
    //s+=0.5*random(-1,3);
    s+=0.5;
    sat+=3;
    brite+=1;
  }

  void ink() {
    colorMode(HSB);
    fill(col, sat, brite, aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    aleph-=2;
    //aleph-=random(1,4);
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;
  float ease=0;

  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  //CGILES: nouveau instancieurs de classe, prenant directement un objet Trendil en paramètre
  Pollen(Tendril lastTrendil) {//instance d'objet Tendril avec pour nom lastTendril
    posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
  }

  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }
  
  void update2(float nValX, float nValY) {
    for (int i=0;i<nbr;i++) {
      posP.set(posP.x+(nValX*ease), posP.y-(nValY*ease), 0);
      evapo+=0.04;
    }
    ease+=0.01;
  }

  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
/* ****************************************************************** */
class PollenManager {
  //CGILES: typage des arraylist en java 1.5, super pratique
  //CGILES: l'arraylist renverra directement des objet selon le type demandé
  //CGILES: ci dessus une arraylist Pollen et une arraylist Tendril
  ArrayList<Pollen> pollens;
  ArrayList<Tendril> tendrils;
  float ang;// pour le calcul de position de Tendril
  int k;// pour le calcul de ang
  float[] xList=new float[nbr];// liste de x pour les instances de Pollen (sauf la première)
  float nValX, nValY, nScale=0.05, m=0.00, n=1.00;

  PollenManager() {
    tendrils = new ArrayList();
    pollens=new ArrayList();
    ang=0;
    k=(int)random(0, 1000);
    for(int i=0;i<nbr;i++) {
      xList[i]=random(-100, 100);
    }
  }

  void update() {
    ang += map(noise(k/50), 0, 1, -10, 10);
    k++;
    tendrils.add( new Tendril(width / 2, height / 2));
    //CGILES:retrait de la création de lastTrendril), car l'arraylist est typée
  /* CGILES : utilisation du nouveau créateur d'instance, 
  et on prend les valeur x et y du premier tendril 
  pour les mettre dans  le dernier element de la liste pollens*/
    pollens.add(new Pollen(tendrils.get(0)));//ajouter un élément pollens

    if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
      tendrils.remove(0);//on enlève le premier élément tendrils
    }
    if (pollens.size()>nbr) {
      pollens.remove(0);
    }

    for (int i=0;i<tendrils.size();i++) {
      tendrils.get(i).update(ang);
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(0).update(ang);
    }
  }
  
  void update2() {
    for (int j=1;j<pollens.size()-1;j++) {// déplacer cette boucle dans update2 de Pollen
      nValX=noise((n+xList[j])*nScale);
      nValY=noise((m+j)*nScale);
      pollens.get(j).update2(nValX, nValY);
    }
    m+=0.08;
    n=m+0.01;
  }
  
  void  display() {
    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).ink();
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).ink();
    }
  }
}

Pendant le premier tour de boucle draw tout va bien, mais rapidement les instances de Pollens cessent de suivre les coordonnées issues de noise pour ne suivre que le trajet de Tendril... J'ai dû commettre une erreur au niveau de la fonction update de PollenManager, quelqu'un aurait-il une idée?

Ars Robota — 2012-02-08 18:30:12

up?

Ars Robota — 2012-02-08 18:56:04

Yahou! J'ai trouvé: il suffisait de copier la ligne

xList[i]=random(-100, 100);

depuis le constructeur de PollenManager vers la fonction update2 du même PollenManager. Seul petit soucis à régler: les instances de Pollen partent inévitablement vers la droite, ce qui est logique puisque j'ai dans update2 de Pollen posP.set(posP.x+(nValX*ease), posP.y-(nValY*ease), 0).

Malheureusement je dois être désespérément trop con pour comprendre le fonctionnement de la fonction noise(), donc je fais plus du bricolage qu'autre chose...

Voici le code complet (qui mérite certainement d'être nettoyé...)

PollenManager pollenManager;// PollenManager appelera Tendril et Pollen
float ang = 0;
// CGILES : incrémenteur pour le noise
float j=random(0,1000);
int nbr=50;// nombre d'instances de Pollen

void setup() {
  size(400, 400);
  frameRate(30);
  smooth();
  pollenManager=new PollenManager();
}

void draw() {
  background(255);
  pollenManager.update();
  pollenManager.update2();
  pollenManager.display();
  //CGILES : au lieu d'utiliser un random , utilisation d'un noise
  //CGILES: le noise est aléatoire mais lisse : http://en.wikipedia.org/wiki/Perlin_noise
}
/* ****************************** */
class Tendril {
  public PVector posT;
  float col = 0;
  float sat=0;
  float brite=0;
  float aleph=255;
  float s=2;

  Tendril(float _x, float _y) {//déclaration du PVector de position de Tendril
    posT = new PVector(_x, _y);
  }

  void update(float ang) {
    posT.set(posT.x + 3 * cos(radians(ang)), posT.y + 3 * sin(radians(ang)), 0);
    //s+=0.5*random(-1,3);
    s+=0.5;
    sat+=3;
    brite+=1;
  }

  void ink() {
    colorMode(HSB);
    fill(col, sat, brite, aleph);
    noStroke();
    ellipse(posT.x, posT.y, s, s);
    aleph-=2;
    //aleph-=random(1,4);
  }
}
/* ************************************************ */
class Pollen {
  PVector posP;
  float evapo=0;
  float ease=0;

  Pollen(float _x, float _y) {
    posP=new PVector(_x, _y);
  }
  //CGILES: nouveau instancieurs de classe, prenant directement un objet Trendil en paramètre
  Pollen(Tendril lastTrendil) {//instance d'objet Tendril avec pour nom lastTendril
    posP=new PVector(lastTrendil.posT.x, lastTrendil.posT.y);
  }

  void update(float ang) {
    posP.set(posP.x + 3 * cos(radians(ang)), posP.y + 3 * sin(radians(ang))-evapo, 0);
    evapo+=0.04;
  }
  
  void update2(float nValX, float nValY) {
    for (int i=0;i<nbr;i++) {
      posP.set(posP.x+(nValX*ease), posP.y-(nValY*ease), 0);
      evapo+=0.04;
    }
    ease+=0.01;
  }

  void ink() {
    noFill();
    stroke(0, 255, 0);
    ellipse(posP.x, posP.y, 8, 8);
  }
}
/* ****************************************************************** */
class PollenManager {
  //CGILES: typage des arraylist en java 1.5, super pratique
  //CGILES: l'arraylist renverra directement des objet selon le type demandé
  //CGILES: ci dessus une arraylist Pollen et une arraylist Tendril
  ArrayList<Pollen> pollens;
  ArrayList<Tendril> tendrils;
  float ang;// pour le calcul de position de Tendril
  int k;// pour le calcul de ang
  float[] xList=new float[nbr];// liste de x pour les instances de Pollen (sauf la première)
  float nValX, nValY, nScale=0.05, m=0.00, n=1.00;

  PollenManager() {
    tendrils = new ArrayList();
    pollens=new ArrayList();
    ang=0;
    k=(int)random(0, 1000);
    for(int i=0;i<nbr;i++) {
      xList[i]=random(-100, 100);
    }
  }

  void update() {
    ang += map(noise(k/50), 0, 1, -10, 10);
    k++;
    tendrils.add( new Tendril(width / 2, height / 2));
    //CGILES:retrait de la création de lastTrendril), car l'arraylist est typée
  /* CGILES : utilisation du nouveau créateur d'instance, 
  et on prend les valeur x et y du premier tendril 
  pour les mettre dans  le dernier element de la liste pollens*/
    pollens.add(new Pollen(tendrils.get(0)));//ajouter un élément pollens

    if (tendrils.size() > 100) {//si on dépasse le nombre d'élément tendrils
      tendrils.remove(0);//on enlève le premier élément tendrils
    }
    if (pollens.size()>nbr) {
      pollens.remove(0);
    }

    for (int i=0;i<tendrils.size();i++) {
      tendrils.get(i).update(ang);
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(0).update(ang);
    }
  }
  
  void update2() {
    for (int j=1;j<pollens.size()-1;j++) {// déplacer cette boucle dans update2 de Pollen
      xList[j]=random(-100, 100);
      nValX=noise((n+xList[j])*nScale);
      nValY=noise((m+j)*nScale);
      pollens.get(j).update2(nValX, nValY);
    }
    m+=0.08;
    n=m+0.01;
  }
  
  void  display() {
    for (int i = 0; i < tendrils.size(); i++) {
      tendrils.get(i).ink();
    }
    for (int i=0;i<pollens.size();i++) {
      pollens.get(i).ink();
    }
  }
}