How to switch from one text to another according to time with the Geomerative library?!

edited June 2018 in Library Questions

Hi, I have an issue with Geomerative. I'd like to switch from text to text using this library according to a time schedule. It works but when switching to a shorter text I still see the previous text! How can I switch properly from a text to another?! Thanks a lot in advance for your help. Best, L

import geomerative.*;
// Liste de liste de points. La 1ère correspond au nombre de phrases, ici 4, la 2ème correspond au nom total de points par phrase
RPoint[][] myPoints = new RPoint[4][0];
RFont font;

String [] FR1 = {
  "On me dit de te haïr et je m'y efforce", 
  "Je t'imagine cruel, violent, implacable", 
  "Mais à te voir je n'ai bientôt plus de force", 
  "Et de te blesser je suis bien incapable", 
}; 
String [] FR2 = {
  "Tous mes camarades combattent avec rage", 
  "Et pleurent la nuit au souvenir des supplices", 
  "Infligés à leurs frères qui sont du même âge", 
  "et rêvent comme eux de toucher une peau lisse"
}; 
String [] FR3 = {
  "Et de pouvoir enfin caresser des obus", 
  "Autres que ceux produits par le pouvoir obtus", 
  "Je rêve de quitter ces boyaux infernaux"
};
String [] FR4 = {
  "De laisser ces furieux des deux bords du Rhin", 
  "Et de pouvoir embrasser ta chute de rein", 
  "Et porter notre amour sur les fonts baptismaux"
};

final color textColor = color(245);
// TIME
int startTime;


//----------------SETUP---------------------------------

void setup() {
  size(1920, 1080, JAVA2D);

  smooth();
  RG.init(this);
  font = new RFont("FreeSans.ttf", 86, CENTER);
  stroke(textColor);
  strokeWeight(0.05);
  //INIT
  initAll();
  changePhrases(0);
  changePhrases(1);
  changePhrases(2);
  changePhrases(3);
  // TIME
  startTime=millis();
}

//----------------DRAW---------------------------------

void draw() {
  background(255);



  translate(width/2, height/1.5);

  for (int i=0; i< myPoints.length; i++) {
    for (int j=0; j< myPoints[i].length-1; j++) {

      pushMatrix(); 
      translate(myPoints[i][j].x, myPoints[i][j].y-420+i*180);
      noFill();
      stroke(0, 200);
      strokeWeight(0.25);
      float angle = TWO_PI*10;
      rotate(j/angle);
      bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);
      //bezier(-10*(noise(20))+mouseX/15, 30+mouseY/10, -10*(noise(10))+mouseX/15, 20+mouseY/15, -20*noise(20)+mouseX/15, -20+mouseY/5, 10+mouseX/15, -10+mouseY/15);
      popMatrix();
    }
  }
  if (millis()-startTime > 0 && millis()-startTime < 3000) {
    changePhrases(0);
  }

  if (millis()-startTime > 3000 && millis()-startTime < 6000) {
    changePhrases(1);
  }

  if (millis()-startTime > 6000 && millis()-startTime < 9000) {
    changePhrases(2);
  }

  if (millis()-startTime > 9000 && millis()-startTime < 12000) {
    changePhrases(3);
  }

}

//----------------INITIALIZE---------------------------------
void initAll() {
  for (int j=0; j<FR1.length; j++) {
    RGroup myGroup = font.toGroup(FR1[j]);
    myGroup = myGroup.toPolygonGroup();
    myPoints[j] = myGroup.getPoints();
  }
}

//FUNCTION TO SWITCH PHRASES
void changePhrases(int state) {

  switch(state) {
  case 0:
    for (int j=0; j<FR1.length; j++) {
      RGroup myGroup = font.toGroup(FR1[j]);
      myGroup = myGroup.toPolygonGroup();
      myPoints[j] = myGroup.getPoints();
    }
    break;
  case 1:
    for (int j=0; j<FR2.length; j++) {
      RGroup myGroup = font.toGroup(FR2[j]);
      myGroup = myGroup.toPolygonGroup();
      myPoints[j] = myGroup.getPoints();
    }
    break;
  case 2:
    for (int j=0; j<FR3.length; j++) {
      RGroup myGroup = font.toGroup(FR3[j]);
      myGroup = myGroup.toPolygonGroup();
      myPoints[j] = myGroup.getPoints();
    }
    break;
  case 3:
    for (int j=0; j<FR4.length; j++) {
      RGroup myGroup = font.toGroup(FR4[j]);
      myGroup = myGroup.toPolygonGroup();
      myPoints[j] = myGroup.getPoints();
    }
    break;
  }
}
//////////////////////////////////////////////

Answers

  • edited May 2018 Answer ✓

    Your array myPoints is [4][0]. In changePhrases, you loop over it and update each row of myPoints based on the length of FR1, or FR2, et cetera. But FR3 and FR4 are only three lines long, so the fourth row of myPoints is never overwritten.

    One way to fix this is to add a fourth, blank line to FR3 and FR4. Another way is to replace myPoints completely with e.g. new RPoint[FR3.length][0] rather than updating it -- now it will always be the correct length, with no extra lines.


    There are other things that could be cleaned up which would make your code easier to edit -- keeping an array of string arrays, changing the way that your timers work, making changePhrases accept a String[] array or an index (rather than a switch statement that is manually wired to different parts of a String[][] array).

  • edited May 2018 Answer ✓

    Look at this cleaned up code for comparison. It is your sketch with minor changes: it uses a set of sets of strings rather than referring to them manually -- this means you can just add more sets of phrases without needing to update the code, and it will just work. Phrases can be any number of lines, 2 lines or 10. There are two functions -- a timer, and a drawing function that renders the phrase strings to RPoints.

    import geomerative.*;
    RPoint[][] myPoints = new RPoint[4][0];
    RFont font;
    
    String[][] phraseSets = new String[4][0];
    String [] FR1 = {
      "On me dit de te haïr et je m'y efforce", 
      "Je t'imagine cruel, violent, implacable", 
      "Mais à te voir je n'ai bientôt plus de force", 
      "Et de te blesser je suis bien incapable", 
    }; 
    String [] FR2 = {
      "Tous mes camarades combattent avec rage", 
      "Et pleurent la nuit au souvenir des supplices", 
      "Infligés à leurs frères qui sont du même âge", 
      "et rêvent comme eux de toucher une peau lisse"
    }; 
    String [] FR3 = {
      "Et de pouvoir enfin caresser des obus", 
      "Autres que ceux produits par le pouvoir obtus", 
      "Je rêve de quitter ces boyaux infernaux"
    };
    String [] FR4 = {
      "De laisser ces furieux des deux bords du Rhin", 
      "Et de pouvoir embrasser ta chute de rein", 
      "Et porter notre amour sur les fonts baptismaux"
    };
    
    final color textColor = color(245);
    // TIME
    int startTime;
    int index;
    int duration;
    int linespacing;
    int fontsize;
    
    //----------------SETUP---------------------------------
    
    void setup() {
      size(900, 600, JAVA2D);
      // add phrases to list
      phraseSets[0] = FR1;
      phraseSets[1] = FR2;
      phraseSets[2] = FR3;
      phraseSets[3] = FR4;
      smooth();
      RG.init(this);
      font = new RFont("FreeSans.ttf", 40, CENTER);
      stroke(textColor);
      strokeWeight(0.05);
      drawPhrases(phraseSets[0]);
      // TIME
      startTime = millis();
      index = 0;         // starting set of phrases
      duration = 2000;   // timer length
      linespacing = 100; // space between phrase lines
    }
    
    //----------------DRAW---------------------------------
    
    void draw() {
      background(255);
      // draw from the center of the screen  
      translate(width/2, height/2);
      // vertically center text block by moving the top up by half the line spaces
      translate(0, -1.0 * linespacing * (phraseSets[index].length-1)/2.0);
      // loop through lines
      for (int i=0; i< myPoints.length; i++) {
        // draw a line
        for (int j=0; j< myPoints[i].length-1; j++) {
          pushMatrix(); 
          translate(myPoints[i][j].x, myPoints[i][j].y);
          noFill();
          stroke(0, 200);
          strokeWeight(0.25);
          float angle = TWO_PI*10;
          rotate(j/angle);
          bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);
          popMatrix();
        }
        // move to the next line
        translate(0, linespacing);
      }
      // check timer, and redraw phrases if time has passed 
      changePhraseTimer(duration, phraseSets);
    }
    
    //----------------FUNCTIONS---------------------------------
    
    /**
     * Timer will change phrases whenever to the next index
     * every time duration milliseconds passes.
     * Restarts itself by updating the global variable startTime.
     */
    void changePhraseTimer(int duration, String[][] phraseSets) {
      if (millis()-startTime > duration) {
        index = (index+1) % phraseSets.length;
        println(index);
        startTime = millis();
        drawPhrases(phraseSets[index]);
      }
    }
    
    /**
     * Renders a String[] array as a geomerative RGroup
     * (PolygonGroup) of points, then stores the points in
     * the global RPoint[][] array myPoints.
     */
    void drawPhrases(String[] phrases) {
      myPoints = new RPoint[phrases.length][0];
      for (int j=0; j<phrases.length; j++) {
        RGroup myGroup = font.toGroup(phrases[j]);
        myGroup = myGroup.toPolygonGroup();
        myPoints[j] = myGroup.getPoints();
      }
    }
    //////////////////////////////////////////////
    

    GeomTextClear--screenshot2

  • edited June 2018

    Dear Jeremy, thank you so much for your great help. I'm not at home but asap I'll implement the complete code with the part of the code you wrote and will let you know. What if the variable 'duration' is not the same for each loop?! Thanks a lot, L

  • Dear Jeremy what if I'd like to have a variable changePhraseTimer function?! 3 seconds for the 1rst phrase 1second pause 2 seconds for the 2nd phrase 1 second pause

    I tried in many ways, but I can't solve the problem... Thanks a lot in adavance. Best, L

  • then post one of your ways here

  • with pleasure, here it is :

    import geomerative.*;
    RPoint[][] myPoints = new RPoint[4][0];
    RFont font;
    
    String[][] phraseSets = new String[4][0];
    String [] FR1 = {
      "On me dit de te haïr et je m'y efforce", 
      "Je t'imagine cruel, violent, implacable", 
      "Mais à te voir je n'ai bientôt plus de force", 
      "Et de te blesser je suis bien incapable", 
    }; 
    String [] FR2 = {
      "Tous mes camarades combattent avec rage", 
      "Et pleurent la nuit au souvenir des supplices", 
      "Infligés à leurs frères qui sont du même âge", 
      "et rêvent comme eux de toucher une peau lisse"
    }; 
    String [] FR3 = {
      "Et de pouvoir enfin caresser des obus", 
      "Autres que ceux produits par le pouvoir obtus", 
      "Je rêve de quitter ces boyaux infernaux"
    };
    String [] FR4 = {
      "De laisser ces furieux des deux bords du Rhin", 
      "Et de pouvoir embrasser ta chute de rein", 
      "Et porter notre amour sur les fonts baptismaux"
    };
    
    final color textColor = color(245);
    // TIME
    int startTime;
    int index;
    int duration;
    int linespacing;
    int fontsize;
     float dur1;
    float dur2;
    int state;
    //----------------SETUP---------------------------------
    
    void setup() {
      size(900, 600, JAVA2D);
      // add phrases to list
      phraseSets[0] = FR1;
      phraseSets[1] = FR2;
      phraseSets[2] = FR3;
      phraseSets[3] = FR4;
      smooth();
      RG.init(this);
      font = new RFont("FreeSans.ttf", 40, CENTER);
      stroke(textColor);
      strokeWeight(0.05);
      drawPhrases(phraseSets[0]);
      // TIME
      startTime = millis();
      index = 0;         // starting set of phrases
      duration = 2000;   // timer length
      linespacing = 100; // space between phrase lines
    }
    
    //----------------DRAW---------------------------------
    
    void draw() {
      background(255);
      // draw from the center of the screen  
      translate(width/2, height/2);
      // vertically center text block by moving the top up by half the line spaces
      translate(0, -1.0 * linespacing * (phraseSets[index].length-1)/2.0);
      // loop through lines
      for (int i=0; i< myPoints.length; i++) {
        // draw a line
        for (int j=0; j< myPoints[i].length-1; j++) {
          pushMatrix(); 
          translate(myPoints[i][j].x, myPoints[i][j].y);
          noFill();
          stroke(0, 200);
          strokeWeight(0.25);
          float angle = TWO_PI*10;
          rotate(j/angle);
          bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);
          popMatrix();
        }
        // move to the next line
        translate(0, linespacing);
      }
      // check timer, and redraw phrases if time has passed 
      changePhraseTimer(duration, phraseSets);
    }
    
    //----------------FUNCTIONS---------------------------------
    
    /**
     * Timer will change phrases whenever to the next index
     * every time duration milliseconds passes.
     * Restarts itself by updating the global variable startTime.
     */
    void changePhraseTimer(int dur1, String[][] phraseSets) {
      dur1 = 3000;
      dur2=6000;
      if (millis()-startTime < dur1) {
        state=0;
      } else if (millis()-startTime < dur1*2) {
        state=1;
      } else if (millis()-startTime < dur1*3) {
        state=2;
      } else if (millis()-startTime < dur1*4) {
        state=3;
      } else {
        state=0;
        startTime = millis();
      }
    
      switch(state) {
    
      case 0:
        drawPhrases(phraseSets[0]);
        break;
      case 1:
        drawPhrases(phraseSets[1]); 
        break;
      case 2:
        drawPhrases(phraseSets[2]);
        break;
      case 3:
        drawPhrases(phraseSets[3]);
        break;
      }
    }
    
    /**
     * Renders a String[] array as a geomerative RGroup
     * (PolygonGroup) of points, then stores the points in
     * the global RPoint[][] array myPoints.
     */
    void drawPhrases(String[] phrases) {
      myPoints = new RPoint[phrases.length][0];
      for (int j=0; j<phrases.length; j++) {
        RGroup myGroup = font.toGroup(phrases[j]);
        myGroup = myGroup.toPolygonGroup();
        myPoints[j] = myGroup.getPoints();
      }
    }
    

    It somehow works but not as I wish! Thanks for your answer.

    L

  • Dear Chrisir, In fact my problem is linked to the attarctor in my main sketch. I switch from a phrase to the other and the attractor for the lines works too but no the attractor linked to the words !? Don't find why... I tried to debug, but don't succeed. Here is the code: Thanks for your help... best, L

    import generativedesign.*;
    import geomerative.*;
    import ddf.minim.analysis.*;
    import ddf.minim.*;
    // List of a list of points. 1rst the numbre of phrases: 4,  the 2nd indicate the number of points
    RPoint[][] myPoints = new RPoint[5][0];
    RFont font;
    PFont f;
    Attractor attractor;
    
    // Variables for lines
    Attractor_Lines attractor_Lines;
    int xCount=401;
    int yCount=401;
    float gridSizeX=1800;
    float gridSizeY=1000;
    Node [] myNodes;
    float xPos, yPos;
    
    String [][] phraseSets = new String [4][0];
    String [] FR1 = {
      "On me dit de te haïr et je m'y efforce", 
      "Je t'imagine cruel, violent, implacable", 
      "Mais à te voir je n'ai bientôt plus de force", 
      "Et de te blesser je suis bien incapable", 
    };
    String [] FR2 = {
      "Tous mes camarades combattent avec rage", 
      "Et pleurent la nuit au souvenir des supplices", 
      "Infligés à leurs frères qui sont du même âge", 
      "et rêvent comme eux de toucher une peau lisse"
    };
    String [] FR3 =
      {"Et de pouvoir enfin caresser des obus", 
      "Autres que ceux produits par le pouvoir obtus", 
      "Je rêve de quitter ces boyaux infernaux"
    };
    String [] FR4 = {
      "De laisser ces furieux des deux bords du Rhin", 
      "Et de pouvoir embrasser ta chute de rein", 
      "Et porter notre amour sur les fonts baptismaux"
    };
    
    //TEXT
    final color textColor = color(245);
    int fontSize;
    
    //SOUND
    Minim minim;
    AudioPlayer[] sounds;
    FFT fft;
    float bandHeight;
    float soundDuration ;
    float soundDuration1 ;
    String []fileNamesFR= {"FR_01", "FR_02", "FR_03", "FR_04", "FR_05", "FR_06", "FR_07", "FR_08", "FR_09", "FR_10", "FR_11", "FR_12", "FR_13", "FR_14"};
    SoundManager sm;
    
    // TIME
    int startTime;
    int initTime;
    int lineSpacing;
    int index;
    int state;
    float duration;
    float dur1;
    float dur2;
    //----------------SETUP---------------------------------------------------------------------------------------
    
    void setup() {
      size(1920, 1080, JAVA2D);
      //add phrases to list
      phraseSets[0]=FR1;
      phraseSets[1]=FR2;
      phraseSets[2]=FR3;
      phraseSets[3]=FR4;
    
      smooth();
      RG.init(this);
      font = new RFont("FreeSans.ttf", 86, CENTER);
      stroke(textColor);
      strokeWeight(0.05);
      //INIT
      drawPhrases(phraseSets[0]);
    
      // LINES initiate attractor + attractors specs
      myNodes = new Node [xCount*yCount];
      initGrid();
      attractor_Lines = new Attractor_Lines(0, 0);
      attractor_Lines.strength=-160;
      attractor_Lines.ramp = 0.85;
    
      //SOUND
      minim = new Minim(this);
      sounds = new AudioPlayer[fileNamesFR.length];
      for (int idx=0; idx<sounds.length; idx++) {
        sounds[idx] = minim.loadFile(fileNamesFR[idx]+".wav", 2048);
        fft = new FFT(sounds[idx].bufferSize(), sounds[idx].sampleRate());
      }
      soundDuration = 2000;
      sm=new SoundManager(this);
      //}
      // TIME
      startTime=millis();
      initTime=millis();
      index=0;
      lineSpacing =150;
    }
    
    //----------------DRAW---------------------------------------------------------------------------------------------
    
    void draw() {
      background(255);
      state =0;
    
      //SOUNDS ANALYZIS
      for (int idx=0; idx < sounds.length; idx++) {
        fft.forward(sounds[idx].mix);
        for (int i =0; i< fft.specSize(); i++) {
          float bandDB = 10*log(fft.getBand(i)/fft.timeSize());
          bandDB = constrain(bandDB, -1000, 1000);
          bandHeight = map(bandDB*4, 0, -220, 0, height);
          stroke(0);
          //line(i, height, i, bandHeight-fft.getBand(i)*8);
        }
      }
    
    
      // LINES
      if (millis()-startTime > 0) {
        for (int i = 0; i<myNodes.length; i=i+10) {
          pushMatrix();
          translate(myNodes[i].x, myNodes[i].y);
          stroke(0, 100);
          strokeWeight(0.01);
          float noiseXRange = attractor_Lines.x/100.0;
          float noiseYRange = attractor_Lines.y/1000.0;
          float noiseX = map(myNodes[i].x, 0, xCount, 0, noiseXRange/5);
          float noiseY = map(myNodes[i].y, 0, yCount, 0, noiseYRange/5);
          float noiseValue = noise(noiseX, noiseY);
          float angle = noiseValue*TWO_PI;
          rotate(angle);
          line(0, 0, 10, 10);
          popMatrix();
        }
      }
    
      // TEXTS
      // draw on the center of the screen
      translate(width/2, height/2);
      // draw phrases vertically centered by moving the top up by half the line spaces
      translate(0, -1.0*lineSpacing*(phraseSets[index].length-1)/2.0);
      // loop through lines
      for (int i=0; i< myPoints.length; i++) {
        // draw a line
        for (int j=0; j< myPoints[i].length-1; j++) {
          pushMatrix(); 
          translate(myPoints[i][j].x, myPoints[i][j].y);
          noFill();
          stroke(0, 200);
          strokeWeight(0.25);
          float angle = TWO_PI*10;
          rotate(j/angle);
          bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);
          //bezier(-10*(noise(20))+mouseX/15, 30+mouseY/10, -10*(noise(10))+mouseX/15, 20+mouseY/15, -20*noise(20)+mouseX/15, -20+mouseY/5, 10+mouseX/15, -10+mouseY/15);
          popMatrix();
        }
        // move to the next line
        translate(0, lineSpacing);
      }
      //check Timer and redraw phrases if time has passed
    
      changePhraseTimerN(dur1, phraseSets);
      sm.update();
      // changePhraseTimer(duration*4, phraseSets);
    }
    
    //----------------INITIALIZE----------------------------------------------------------------------------------------------------------------------------------------
    void drawPhrases(String [] phrases) {
      myPoints = new RPoint[phrases.length][0];
      for (int j=0; j<phrases.length; j++) {
        RGroup myGroup = font.toGroup(phrases[j]);
        myGroup = myGroup.toPolygonGroup();
        myPoints[j] = myGroup.getPoints();
      }
    }
    
    //----------------TIMER----------------------------------------------------------------------------------------------------------------------------------------
    
    /*void changePhraseTimer( float duration, String [][] phraseSets) {
      duration = sounds[0].length()-150;
      if (millis()-startTime > duration*4) {
        index =(index+1) % phraseSets.length; 
        drawPhrases(phraseSets[index]);
        //startTime = millis();
      }
    }*/
    
    void changePhraseTimerN(float dur1, String [][] phraseSets) {
      dur1 = 11200.;
      dur2=7000;
      if (millis()-startTime < dur1) {
        state=0;
      } else if (millis()-startTime < dur1*2-200.) {
        state=1;
      } else if (millis()-startTime < dur1*3-4500.) {
        state=2;
      } else if (millis()-startTime < dur1*4-9500.) {
        state=3;
      } else {
        state=0;
        startTime = millis();
      }
    
      switch(state) {
    
      case 0:
        drawPhrases(phraseSets[0]);
        //println(0);
        index=0;
        break;
      case 1:
        //drawPhrases(phraseSets[1]); 
        index = (index+1) % phraseSets.length;
        println(index);
        startTime = millis();
        drawPhrases(phraseSets[index]);
        // println(1);
        break;
      case 2:
        drawPhrases(phraseSets[2]);
        // println(2);
        break;
      case 3:
        drawPhrases(phraseSets[3]);
        // println(3);
        break;
      }
    }
    
    
    //----------------TEXT ATTRACTOR INIT----------------------------------------------------------------------------------------------------------------------------------------
    void initAttractor(int i) {
      if (i>=4 && i<8) {
        i-=4;
      } else if (i>=8 && i<11) {
        i-=8;
      } else if (i>=11 && i<14) { 
        i-=11;
      } else if (i>14) {
        i=0;
      }
    
      float x = 0;
      float y =-50; 
      // println(i);
      attractor = new Attractor(x, y, myPoints[i]);
    }
    //----------------LINES ATTRACTOR INIT----------------------------------------------------------------------------------------------------------------------------------------
    void updateAttractorLines(float x, float y) {
      attractor_Lines.x=x;
      attractor_Lines.y=y;
    }
    //----------------LINES GRID INIT----------------------------------------------------------------------------------------------------------------------------------------
    void initGrid() {
      int i =0;
      for (int x=0; x<xCount; x++) {
        for (int y=0; y<yCount; y++) {
    
          xPos = x*(gridSizeX /(xCount-1)) + (width-gridSizeX)/2;
          yPos = y*(gridSizeY /(yCount-1)) + (height-gridSizeY)/2;
          myNodes[i] = new Node(xPos, yPos);
          myNodes[i]. setBoundary(0, 0, width, height);
          myNodes[i].setDamping(0.9);
          i++;
        }
      }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    class Attractor {
    
      float force_radious = 100;
      float maxForce = 15;
      RPoint position;
      RPoint[] points;
    
      Attractor(float x, float y, RPoint[] p) {
        points = p;
        position = new RPoint(x, y);
      }
    
      void attract() {
    
        for (int i =0; i < points.length; i++) {
    
          float d= points[i].dist(position);
         // println ("d : "+d);
          if (d < force_radious) {   
            RPoint desired = new RPoint(points[i]);
            //points[i]= new RPoint(points[i]);
            //println( "avant x : "+ points[i].x +" y: "+points[i].y);
            desired.sub(position);
            desired.normalize();
            desired.scale(map(d, 0, force_radious, maxForce, 0));
            points[i].add(desired);
             //println( "après x : "+ points[i].x +" y: "+points[i].y);
          }
        }
      }
      void display () {
        stroke(0);
       strokeWeight(2);
      // ellipse (position.x, position.y-750, 30, 30);
      }
      void moveTo(float x, float y){
        position.x=x;
        position.y=y;
    
      }
    }
    
    class Attractor_Lines {
      float x=0, y=0;
      float radius =110;
      float strength= 0.55;
      float ramp=0.05;
      float theX;
      float theY;
    
      Attractor_Lines( float theX, float theY) {
        x= theX;
        y = theY;
      }
    
      void attract_Lines (Node theNode) {
    
        float dx = x-theNode.x;
        float dy = y-theNode.y;
        float d= mag(dx, dy);
        if ( d > 0 && d < radius) {
    
          float s = pow(d/radius, 1/ramp);
          float f = s*9*strength*50 * (1/(s+1)+((s-3)/4))/d;
          theNode.velocity.x += dx*f;
          theNode.velocity.y += dy*f;
        }
      }
    }
    
    ////////////////////////////////////////////////////////////////
    
    import ddf.minim.analysis.*;
    import ddf.minim.*;
    
    class SoundManager {
      //SOUND
      Minim minim;
      AudioPlayer[] sounds;
      FFT fft;
      float bandHeight;
      int currentSound;
      String []fileNamesFR1= {"FR_01", "FR_02", "FR_03", "FR_04", "FR_05", "FR_06", "FR_07", "FR_08", "FR_09", "FR_10", "FR_11", "FR_12", "FR_13", "FR_14"};
      float []linesYPositions ={300., 450., 600., 750., 300., 450., 600., 750., 450., 600., 750., 450., 600., 750.};
    
      SoundManager(PApplet app) {
    
        minim = new Minim(app);
        currentSound =-1;
        sounds = new AudioPlayer[fileNamesFR1.length];
        for (int idx=0; idx<sounds.length; idx++) {
          sounds[idx] = minim.loadFile(fileNamesFR1[idx]+".wav", 2048);
          fft = new FFT(sounds[idx].bufferSize(), sounds[idx].sampleRate());
    
        }
      }
    
      void update() {
    
        // SOUND
        if (currentSound ==-1) { 
          startPlaying();
    
        } else if (!sounds[currentSound].isPlaying()) {
          playNext();
        } else { 
    
          fft.forward(sounds[currentSound].mix);
          for (int i =0; i< fft.specSize(); i++) {
            float bandDB = 10*log(fft.getBand(i)/fft.timeSize());
            bandDB = constrain(bandDB, -1000, 1000);
            bandHeight = map(bandDB*4, 0, -220, 0, height);
          }
    
          attractor.moveTo(map(sounds[currentSound].position(), 0, sounds[currentSound].length(), 0, width-100)-width/2, bandHeight/10-300);
          attractor.attract();
    
          updateAttractorLines( attractor_Lines.x = map(sounds[currentSound].position(), 0, sounds[currentSound].length(), 0, width-(100)/2), linesYPositions[currentSound]);
    
          for (int j = 0; j<myNodes.length; j++) {
            attractor_Lines.attract_Lines(myNodes[j]);
            myNodes[j].update();
          }
        }
      }
    
    
      void startPlaying() {
        currentSound=0;
        playCurrentSound();
      }
    
      void playNext() {
    
        currentSound++;
        if (currentSound > sounds.length-1) {
          currentSound=0;
          drawPhrases(phraseSets[0]);
        } 
    
        // fonction restartAnimation
        //drawPhrases(phraseSets[0]);
       playCurrentSound();
    
      } 
    
      void playCurrentSound() {
        sounds[currentSound].rewind();
        sounds[currentSound].play();
        initAttractor(currentSound);
      }
    }
    
  • Thanks Chrisir! Actually I partly solved the problem, the attractor deform the text now, but the text is returning back immediatly to its initial state!! I certainly initiate the attractor in the wrong place... I hope @jeremydouglas will have some time to help me later on today!

  • Dear @jeremydouglas if you find some time to help me I'd be very glad! Thanks a lot. Best, L

  • Dear Chrisir and Jeremy, I still have the same problem in my sketch : the attractor deform the text, but the text is returning back immediatly to its initial state!! I certainly initiate the attractor in the wrong place... I've imlemented other parts of the sketch but now I'm stuck with this error. If you can help me I would really appreciate ! Thanks a lot. L

  • Please make sure you provide the latest code and some details or where the problem could be in the code. If you point out what section is not working properly, it could save some time to ppl that are trying to help you.

    Kf

  • ok I will do so thanks a lot ;))

  • Hello @jeremydouglas, Pleasefind below a simple version of my latest code. I have two phraseTimer functions, one works well (phraseTimer()) the others doesn't work properly (phraseTimerALTER()), I don't find why ?! Could you please help me with this issue ? Thanks a lot in adavnce. Best wishes, L

    import geomerative.*;
            RPoint[][] myPoints = new RPoint[4][0];
            RFont font; 
            String[][] phraseSets = new String[4][0];
            String [] FR1 = {  "On me dit de te haïr et je m'y efforce",   "Je t'imagine cruel, violent, implacable",   "Mais à te voir je n'ai bientôt plus de force",   "Et de te blesser je suis bien incapable", }; 
            String [] FR2 = {  "Tous mes camarades combattent avec rage",   "Et pleurent la nuit au souvenir des supplices",   "Infligés à leurs frères qui sont du même âge",   "et rêvent comme eux de toucher une peau lisse"}; 
            String [] FR3 = {  "Et de pouvoir enfin caresser des obus",   "Autres que ceux produits par le pouvoir obtus",   "Je rêve de quitter ces boyaux infernaux"};
            String [] FR4 = {  "De laisser ces furieux des deux bords du Rhin",   "Et de pouvoir embrasser ta chute de rein",   "Et porter notre amour sur les fonts baptismaux"};
             final color textColor = color(245);
            // TIME
            int startTime;
            int index;
            int duration;
            int linespacing;
            int fontsize; 
            //----------------SETUP--------------------------------- 
    
            void setup() {  
            size(900, 600, JAVA2D);  
            // add phrases to list  
            phraseSets[0] = FR1;  
            phraseSets[1] = FR2;  
            phraseSets[2] = FR3;  
            phraseSets[3] = FR4;  
            smooth();  
            RG.init(this);  
            font = new RFont("FreeSans.ttf", 40, CENTER);  
            stroke(textColor);  
            strokeWeight(0.05);  
            drawPhrases(phraseSets[0]);  
            // TIME  
            startTime = millis();  
            index = 0;         
            // starting set of phrases  
           duration = 2000;   
            // timer length 
             linespacing = 100; 
            // space between phrase lines} 
    
            //----------------DRAW--------------------------------- 
    
            void draw() {
              background(255);  
            // draw from the center of the screen    
            translate(width/2, height/2);  
            // vertically center text block by moving the top up by half the line spaces  
    
            translate(0, -1.0 * linespacing * (phraseSets[index].length-1)/2.0);  
            // loop through lines  
            for (int i=0; i< myPoints.length; i++) {  
              // draw a line   
             for (int j=0; j< myPoints[i].length-1; j++) {      
            pushMatrix();       
            translate(myPoints[i][j].x, myPoints[i][j].y);      
            noFill();      
            stroke(0, 200);      
            strokeWeight(0.25);      
            float angle = TWO_PI*10;      
            rotate(j/angle);      
            bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);          
            popMatrix();    
            }    
            // move to the next line   
             translate(0, linespacing);  
            }  
            // check timer, and redraw phrases if time has passed   
        changePhraseTimer(duration, phraseSets);
        changePhraseTimerALTER(dur1, phraseSets);
            } 
    
            //----------------FUNCTIONS--------------------------------- 
    
            /** * Timer will change phrases whenever to the next index * every time duration milliseconds passes. * Restarts itself by updating the global variable startTime. */
    
            void changePhraseTimer(int duration, String[][] phraseSets) {
              if (millis()-startTime > duration) {
                index = (index+1) % phraseSets.length; 
               println(index);   
             startTime = millis();    
            drawPhrases(phraseSets[index]); 
             }
            }
    
        void changePhraseTimerALTER(float dur1, String [][] phraseSets) {  
        dur1 = 11200.;
    
         if (millis()-startTime < dur1) {   
         state=0;  
        } else if (millis()-startTime < dur1*2-200.) {
           state=1; 
         } else if (millis()-startTime < dur1*3-4500.) {
            state=2;  
        } else if (millis()-startTime < dur1*4-9000.) {
            state=3;  
        } 
        else {    
        state=0;    
        startTime = millis();  
        }   
    
        switch(state) {   
        case 0:    
        drawPhrases(phraseSets[0]);
        break; 
         case 1:    
        drawPhrases(phraseSets[1]);        
        break;  
        case 2:    
        drawPhrases(phraseSets[2]);      
        break;  
        case 3:    
        drawPhrases(phraseSets[3]);      
        break;  
        }
        }
             /** * Renders a String[] array as a geomerative RGroup * (PolygonGroup) of points, then stores the points in * the global RPoint[][] array myPoints. */
    
            void drawPhrases(String[] phrases) { 
             myPoints = new RPoint[phrases.length][0];  
            for (int j=0; j<phrases.length; j++) {   
             RGroup myGroup = font.toGroup(phrases[j]);   
             myGroup = myGroup.toPolygonGroup();    
            myPoints[j] = myGroup.getPoint(); 
             }
            }
            //////////////////////////////////////////////
    
  • Remember to hit ctrl-t in processing to get better indents automatically

  • Oups, thanks Chrisir, yes sorry I've corrected the indents and fix a bit the code :

    import geomerative.*;        
    RPoint[][] myPoints = new RPoint[4][0];        
    RFont font;         
    String[][] phraseSets = new String[4][0];        
    String [] FR1 = {  "On me dit de te haïr et je m'y efforce", "Je t'imagine cruel, violent, implacable", "Mais à te voir je n'ai bientôt plus de force", "Et de te blesser je suis bien incapable", };         
    String [] FR2 = {  "Tous mes camarades combattent avec rage", "Et pleurent la nuit au souvenir des supplices", "Infligés à leurs frères qui sont du même âge", "et rêvent comme eux de toucher une peau lisse"};         
    String [] FR3 = {  "Et de pouvoir enfin caresser des obus", "Autres que ceux produits par le pouvoir obtus", "Je rêve de quitter ces boyaux infernaux"};        
    String [] FR4 = {  "De laisser ces furieux des deux bords du Rhin", "Et de pouvoir embrasser ta chute de rein", "Et porter notre amour sur les fonts baptismaux"};         
    final color textColor = color(245);     
    // TIME
    int startTime;
    int index;        
    int duration; 
    int linespacing; 
    int fontsize;  
    int state=0;
    int dur1;
    //----------------SETUP--------------------------------- 
    void setup() {   
      size(900, 600, JAVA2D);
      // add phrases to list
      phraseSets[0] = FR1;
      phraseSets[1] = FR2; 
      phraseSets[2] = FR3; 
      phraseSets[3] = FR4;
      smooth();         
      RG.init(this);
      font = new RFont("FreeSans.ttf", 40, CENTER); 
      stroke(textColor);          
      strokeWeight(0.05);         
      drawPhrases(phraseSets[0]);         
      // TIME       
      startTime = millis();
      index = 0;    
      // starting set of phrases 
      duration = 2000;   
      // timer length    
      linespacing = 100; 
      // space between phrase lines
    }
    
    //----------------DRAW---------------------------------        
    
    void draw() {      
      background(255);         
      // draw from the center of the screen
      translate(width/2, height/2);          
      // vertically center text block by moving the top up by half the line spaces
      translate(0, -1.0 * linespacing * (phraseSets[index].length-1)/2.0);
      // loop through lines    
      for (int i=0; i< myPoints.length; i++) {  
        // draw a line          
        for (int j=0; j< myPoints[i].length-1; j++) {    
          pushMatrix();  
          translate(myPoints[i][j].x, myPoints[i][j].y); 
          noFill();   
          stroke(0, 200); 
          strokeWeight(0.25);
          float angle = TWO_PI*10;
          rotate(j/angle);  
          bezier(-2*(noise(10)), 10, 25*(noise(10)), -5, 2*noise(5), -15, 10, -3);  
          popMatrix();
        }            
        // move to the next line  
        translate(0, linespacing);
      }          
      // check timer, and redraw phrases if time has passed  
      // changePhraseTimer(duration, phraseSets);    
      changePhraseTimerALTER(dur1, phraseSets);
    }         
    
    //----------------FUNCTIONS---------------------------------          
    /** * Timer will change phrases whenever to the next index * every time duration milliseconds passes. * Restarts itself by updating the global variable startTime. */
    void changePhraseTimer(int duration, String[][] phraseSets) {   
      if (millis()-startTime > duration) {
        index = (index+1) % phraseSets.length; 
        println(index);            
        startTime = millis();            
        drawPhrases(phraseSets[index]);
      }
    }     
    
    void changePhraseTimerALTER(float dur1, String [][] phraseSets) {   
      dur1 = 5000;  
    
      if (millis()-startTime > dur1) {   
        drawPhrases(phraseSets[1]);
      }  
      if (millis()-startTime > dur1*2) {     
        drawPhrases(phraseSets[2]);
      } else if (millis()-startTime > dur1*3) {       
        drawPhrases(phraseSets[3]);
      } else if (millis()-startTime > dur1*4) {
        drawPhrases(phraseSets[0]);
        startTime = millis();
      }
    }
    /** * Renders a String[] array as a geomerative RGroup * (PolygonGroup) of points, then stores the points in * the global RPoint[][] array myPoints. */
    void drawPhrases(String[] phrases) { 
      myPoints = new RPoint[phrases.length][0];
      for (int j=0; j<phrases.length; j++) { 
        RGroup myGroup = font.toGroup(phrases[j]);
        myGroup = myGroup.toPolygonGroup();     
        myPoints[j] = myGroup.getPoints();
      }
    }        
    
    //////////////////////////////////////////////
    
  • With pleasure, sorry but between time a friend and I we corrected most of the mistakes, but if I'm stuck today I'll tell you for sure ;)

This discussion has been closed.