Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

  • How do I make the timer stop and reset?

    Still happening.

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    float l = 3375;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown = false;
    boolean e = false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown) {
        difference = 0;
      } else {
        difference = ( millis() - count_at_reset ) /1000;
      }
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        sngdt();
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
    
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    
      if (e) {
        fill(0);
        textSize(52);
        text("Bylb", l, 189);
      }
    
      if (sec > 10) {
        s();
      }
      l--;
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed) {
        return;
      }if (vIsDown) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y--;
      }
    
      else if (key == 's'||key == 'S') {
        y++;
      }
    
     else if (key == 'u'||key == 'U') {
        x--;
      }
    
     else if (key == 'i'||key == 'I') {
        x++;
      }
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = true;
        l = 3375;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    
    void sngdt() {
      rect(25, 200, 90, 90);
    }
    
    void s() {
      e = true;
    }
    

    Also, I made a simple and quick sketch just to test this glitch and I found that it is literally came out of nowhere. I am not kidding. This is the code of that other sketch.

    int x = 200;
    int y = 200;
    
    void setup() {
      size(400, 400); 
      frameRate(60);
    }
    
    void draw() {
      background(0);
      rect(x, y, 20, 20);
      inputs();
    }
    
    void inputs() {
      if (!keyPressed) {
        return;
      }
      if (key == 'w') {
        y--;
      }
      if (key == 's') {
        y++;
      }
      if (key == 'a') {
        x--;
      }
      if (key == 'd') {
        x++;
      }
    }
    
  • How do I make the timer stop and reset?

    I did what you asked (I think) and it partially fixed it. When I put key=0;, it makes me go twice as slow. At first I thought, "Well this will be easy to fix; just make the square go 2 pixels when I press q/s/u/i instead of 1" but then it made the square get this jittery movement. Also, if I press "q" then immediately let go and press "s", then the same problem will happen, but in a different way. Instead of the movement getting applied longer than it should, this happens to the stop (so I press "q" then "s" like I mentioned before then I will stop for half a second instead of continue moving for half a second). Could you help me with this?

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    float l = 3375;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown = false;
    boolean e = false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown) {
        difference = 0;
      } else {
        difference = ( millis() - count_at_reset ) /1000;
      }
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        sngdt();
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
    
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    
      if (e) {
        fill(0);
        textSize(52);
        text("Bylb", l, 189);
      }
    
      if (sec > 10) {
        s();
      }
      l--;
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed || vIsDown) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y-=2;
      }
    
      else if (key == 's'||key == 'S') {
        y+=2;
      }
    
     else if (key == 'u'||key == 'U') {
        x-=2;
      }
    
     else if (key == 'i'||key == 'I') {
        x+=2;
      }
      key=0;
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = true;
        l = 3375;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    
    void sngdt() {
      rect(25, 200, 90, 90);
    }
    
    void s() {
      e = true;
    }
    

    Note that there is a new forum

    What do you mean by this?

  • How do I make the timer stop and reset?

    Hello again. Long time no see. I'm currently having this weird but annoying glitch. If I am holding in a direction (for example I hold 'q' to move up) and then I press in another direction (for example 's' to move down), the first input will still be active for quite a while (so I hold 'q' to move up then immediately let go of 'q' and start holding 's' to move down. I will still be moving up for about a half second).

    Could you help me with this?

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    float l = 3375;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown = false;
    boolean e = false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown) {
        difference = 0;
      } else {
        difference = ( millis() - count_at_reset ) /1000;
      }
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        sngdt();
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
    
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    
      if (e) {
        fill(0);
        textSize(52);
        text("Bylb", l, 189);
      }
    
      if (sec > 10) {
        s();
      }
      l--;
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed || vIsDown) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y--;
      }
    
      if (key == 's'||key == 'S') {
        y++;
      }
    
      if (key == 'u'||key == 'U') {
        x--;
      }
    
      if (key == 'i'||key == 'I') {
        x++;
      }
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = true;
        l = 3375;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown = false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    
    void sngdt() {
      rect(25, 200, 90, 90);
    }
    
    void s() {
      e = true;
    }
    
  • Analogue Clock Second hand Sweep not Tick

    Seconds return seconds as an integer value. You need millis() as it returns fractions of a second.

    it will look like this:

    float s = map( (millis()%1000), 0, 1000, 0, 360);

    This is assuming that seconds() and millis() are internally synchronized. If they are not, then there is another trick. Any other posts, we go to the new forum.

    Kf

  • make text appear letter by letter

    Check this code below. There is an exercise at the end if you decide to pursue it. I am using the computer's clock to keep track of time. When I show a letter, then I tell the computer to show the next letter ONLY when next time is reached, which I define as soon as I change the letter.

    Notice that if you pressed and drag the mouse, you can change the size of the text. There is an extra exercise of changing the rate the letters are shown dragging along the width, for you to do.

    Press P to toggle the play/pause state.

    Keep the reference handy as it will help you in your coding journey:

    https://processing.org/reference/

    For instance, you need this to understand what I did:

    https://processing.org/reference/String_substring_.html

    Notice this is one of many approaches to do this. The way you did it is one way but it is lots to work to change it or include new features. This approach gives more flexibility.

    Finally, there is a new forum: https://discourse.processing.org

    Kf

    boolean begin = false;
    
    int updateRate=120; //units in msecs
    int nextTime;
    
    String mytext="";
    String screenText="";
    int textPosition=0;
    
    void setup() { 
      size (600, 600, JAVA2D);
    
      mytext="Lorem ipsum dolor sit amet, sit tempor. Dui enim, gravida orci in turpis ullamcorper neque enim. Consequat luctus et justo dictum interdum. Mauris fusce, augue orci sit quis in amet,"; 
      mytext+="donec sollicitudin faucibus lobortis rutrum hac, ut curabitur sem ullamcorper sed eget, wisi et morbi lorem commodo augue aliquam. Ante tristique a.";
      mytext+="Sociis a volutpat dui, wisi nunc in ultricies viverra nunc, eos sed habitasse lacus. Purus porttitor ac sed nec ante. Consectetuer mauris lobortis, condimentum luctus quis,";
      mytext+=" cursus dolor dui lacus id mattis mauris, pretium adipiscing congue tempor mauris gravida elit, ex ultrices amet justo. Sit mauris proin placerat ultrices, ut nullam etiam libero.";
      mytext+="Malesuada semper condimentum justo proin, parturient egestas dolor, erat rutrum quis sem ut a. Adipiscing felis, at orci non nunc ut sapien. Hymenaeos malesuada, nulla per aliquam aperiam,";
      mytext+="wisi dolor. At sit feugiat egestas et, tincidunt varius id purus in, malesuada libero, wisi ligula rhoncus nulla massa vel feugiat. Nec sollicitudin. Vel tortor nibh wisi. Mollis sed in";
      mytext+="dapibus vitae morbi elit, consectetuer mauris dolor elementum, purus vel pellentesque in morbi sit.";
      nextTime=-1;
    
      surface.setTitle("Press P to play/pause effect");
    }
    
    
    void draw() {
      background(0);
    
      if (begin && millis()>nextTime) {
    
        textPosition++;
        screenText=mytext.substring(0, textPosition);
    
        nextTime=millis()+updateRate;
      }
    
      text(screenText, 100, 100, 500, 500);
    }
    
    void keyPressed() { 
    
      if (key == 'p' || key == 'P') {   
        begin = !begin;
      }
    }
    
    void mouseDragged(){
    
      textSize(int(map(mouseY,0,height,6,18)));  //Drag along height changes text size
    
      textSize(int(map(mouseY,0,height,6,18)));  //EXERCISE: Drag along width changes typing rate
    
    }
    
  • make text appear letter by letter

    I've made this code thingy but can't find any other way than the one shown down below to make the letters appear one by one :) hope someone can help.

    boolean begin = false;
    int time;
    int elapsedTime;
    
    void setup() { 
      size (600, 600, JAVA2D);
    }
    
    
    void draw() { 
      String start = "This is a quickstory...";
      String story= "";
    
      background(0,0,0);
    
      if (elapsedTime>=1500){  start = start+" and it's a fun one :).."; }
      if (elapsedTime>=3000){  start = start+" but it can quickly get a little hectic!!!"; }
    
      if (elapsedTime>=5000){story = story+"I";}
      if (elapsedTime>=5100){story = story+" ";}
      if (elapsedTime>=5200){story = story+"o";}
      if (elapsedTime>=5300){story = story+"n";}
      if (elapsedTime>=5400){story = story+"c";}
      if (elapsedTime>=5500){story = story+"e";}
      if (elapsedTime>=5600){story = story+" ";}
      if (elapsedTime>=5700){story = story+"t";}
      if (elapsedTime>=5800){story = story+"o";}
      if (elapsedTime>=5900){story = story+"o";}
      if (elapsedTime>=6000){story = story+"k";}
      if (elapsedTime>=6100){story = story+" ";}
      if (elapsedTime>=6200){story = story+"a";}
      if (elapsedTime>=6300){story = story+" ";}
      if (elapsedTime>=6400){story = story+"w";}
      if (elapsedTime>=6500){story = story+"a";}
      if (elapsedTime>=6600){story = story+"l";}
      if (elapsedTime>=6700){story = story+"k";}
      if (elapsedTime>=7500){story = story+" down to the beach but ended up getting cold feet and went home again"; }
    
      if (begin) {
    
        elapsedTime = millis() - time;
        text("Press E to end", 20, 30);
    
        text(start, 20, 50);
        text(story, 20, 70);
    
      }
      else { textAlign(CENTER);text("Press S to start", 300, 300); textAlign(LEFT); }
    
    }
    
    void keyPressed(){ 
        if (key == 's' || key == 'S') {
        time = millis();
        // start music
        begin = true;
      }
        if (key == 'e' || key == 'E') {
        begin = false;
      }
    }
    
  • How can I do headless / virtual screen buffer pixel reading?

    Hi

    I currently have a setup with Processing running on Raspberry Pi, sending artnet messages across multiple universes to some Teensy's to do LED lighting animations using @cansik 's artnet library. I'm running into serious framerate issues - with drawing animations to screen, then reading from screen into a pixel buffer and then sending messages over artnet, it runs at approximately 7fps.

    I know that I can run the whole thing headless, or by not drawing to screen, my fps bumps up to 45-50fps, which is fine, but it limits my ability to make content through creating video or animations and filling my pixel buffer from there. Does anyone know of ways to do this maybe via a virtual screen buffer? The workflow would be create content and read pixels to a pixel buffer from screen during development, and then switch to a virtual buffer when running live.

    Code below. Setting the writeToScreen boolean to false, switches the code to writing directly to the pixel buffer.

    import ch.bildspur.artnet.*;
    import processing.serial.*;
    
    //___________________________
    // setup pattern
    boolean readFromScreen = false;
    boolean writeToScreen = true;
    Pattern patterns[] = {
      new TraceDown(), new TraceDown(), new TraceDown(), new TraceDown(), new FadeTrace(), new TraceDown(), 
      new TraceDown(), new TraceDown(), new TraceDown(), new TraceDown(), new FadeTrace(), new TraceDown(), 
      new TraceDown(), new TraceDown(), new TraceDown()
    };
    
    //___________________________
    // setup artnet 
    ArtNetClient artnet;
    int numUniverse = 15;
    int numChannels = 510;
    byte[] dmxData = new byte[numChannels];
    ArtnetDMX Artnetclass = new ArtnetDMX();
    
    //___________________________
    // stetup serial
    Serial port;  // Create object from Serial class
    String data = "0 0";     // Data received from the serial port
    int[] nums;
    byte[] inBuffer = new byte[4];
    
    int windSpeed;
    int windDir;
    float windSpeedCal;
    
    //___________________________ 
    // setup leds
    int numLeds = 88;
    color led[][] = new color[numChannels/3][numUniverse];
    int size = 2;
    color[][] pixelBuffer = new color[numChannels/3][numUniverse];
    
    //___________________________
    // setup timer
    long[] ellapseTimeMs = new long[numUniverse];
    long[] ellapseTimeMsStartTime = new long[numUniverse];
    float durationMs = 3000;
    boolean direction = true; 
    
    
    //_________________________________________________________
    void setup()
    {
    
      size(300, 80);
      colorMode(HSB, 360, 100, 100);
      textAlign(CENTER, CENTER);
      textSize(20);
    
      // create artnet client without buffer (no receving needed)
      artnet = new ArtNetClient(null);
      artnet.start();
    
      // create port
      //String portName = Serial.list()[0];
      //port = new Serial(this, portName, 2000000);
    }
    
    //_________________________________________________________
    void draw()
    {
      // create color
      int c = color(frameCount % 360, 80, 100);
    
      background(0);
      stroke(0);
    
      //change direction
      if (ellapseTimeMs[0]> durationMs) direction = !direction;
      // choose pattern to run on LED strip
      // int pattern = 0;  
      for (int i = 0; i <numChannels/3; i++) {
        for (int j = 0; j < numUniverse; j++) {
          if (ellapseTimeMs[j]> durationMs) {
            ellapseTimeMsStartTime[j] = 0;
          } else if (direction==true) {
            float position = i/(float)(numChannels/3);
            float remaining = 1.0 - ellapseTimeMs[j]/durationMs;
            if (readFromScreen == false){
              pixelBuffer[i][j] = patterns[j].paintLed(position, remaining, led[i][j]);
            } else {
              led[i][j] = patterns[j].paintLed(position, remaining, led[i][j]);
            }
    
          } else {
            float position = 1.0 - (i/(float)(numChannels/3));
            float remaining = ellapseTimeMs[j]/durationMs;
            if (readFromScreen == false){
              pixelBuffer[i][j] = patterns[j].paintLed(position, remaining, led[i][j]);
            } else {
              led[i][j] = patterns[j].paintLed(position, remaining, led[i][j]);
            }
          }
        }
      }
    
      if (writeToScreen == true) {
        showPattern();
      }
    
      if (readFromScreen == true){
        updatePixelBuffer();
      } 
    
      Artnetclass.updateArtnet(artnet, dmxData, pixelBuffer);
      //oldUpdateArtnet();
    
      updateEllapseTime();
      println(frameRate);
    
      // show values
      //text("R: " + (int)red(c) + " Green: " + (int)green(c) + " Blue: " + (int)blue(c), width-200, height-50);
    }
    
    
    // clock function
    void updateEllapseTime() {
      for (int j = 0; j < numUniverse; j++) {
        if (ellapseTimeMsStartTime[j] == 0) {
          ellapseTimeMsStartTime[j] = millis();
          ellapseTimeMs[j] = 0;
        } else {
          ellapseTimeMs[j] = millis() - ellapseTimeMsStartTime[j];
        }
      }
    }
    
    // storing pixels from screen
    void updatePixelBuffer() {
      for (int i = 0; i < numChannels/3; i++) {
        for (int j = 0; j < numUniverse; j++) {
          // read screen pixels and assign to pixel buffer
          //pixelBuffer[i][j] = get(i*size/2+(size/4), j*size+size/2);
          pixelBuffer[i][j] = get(i*size +size/2, j*size+size/2);
          fill(pixelBuffer[i][j]);
          stroke(pixelBuffer[i][j]);
          rect(50+i, 50+j, 1, 1);
        }
      }
    }
    
    // draw pattern on screen
    void showPattern() {
      for (int i = 0; i < numChannels/3; i++) {
        for (int j = 0; j < numUniverse; j++) {
          // show only pixel buffer if not reading from screen
          if (readFromScreen == false){
              fill(pixelBuffer[i][j]);
            } else {
              fill(led[i][j]);
            }
          rect(i*size+size, j*size+size, size, size);
        }
      }
    }
    
  • How to switch from one text (using Geomerative) to an other according to a changing duration timer?!

    Hello, I asked a very close question brillantly answered by @jeremydouglas few time ago, now I'd like to have a different duration for each text. In the sketch below the changePhraseTimer() works, but not the changePhraseTimerN(), we don't see the last text and it doesn't loop properly. Could someone help me with this issue please ?! Thanks a lot in advance. L

    import generativedesign.*;
    import geomerative.*;
    // 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;
    
    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;
    
    // TIME
    int startTime;
    int initTime;
    int lineSpacing;
    int index;
    int state;
    float duration;
    int dur1;
    
    //----------------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]);
    
       // TIME
      startTime=millis();
      initTime=millis();
      index=0;
      lineSpacing =150;
    }
    
    //----------------DRAW----------------------------------------------------------------------------------
    
    void draw() {
      background(255);
      state =0;
    
    
      // 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();
      //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() {
      dur1=11500;
    
      if (millis()-startTime > dur1+1400) {
        index =(index+1) % phraseSets[1].length; 
        drawPhrases(phraseSets[index]);
        startTime= millis();
      } else if (millis()-startTime > dur1-800) {
        index =(index+1) % phraseSets[2].length; 
        drawPhrases(phraseSets[index]);
        startTime= millis();
      } else if (millis()-startTime > dur1+1000) {
        index =(index+1) % phraseSets[3].length; 
        drawPhrases(phraseSets[index]);
        startTime= millis();
      } else if (millis()-startTime > dur1*2-8000) {
        drawPhrases(phraseSets[0]);
        startTime= millis();
      }
    }
    
    
    //----------------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]);
    }
    
    
    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;
    
      }
    }
    
  • How to switch from one text to another according to time with the Geomerative library?!

    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();
      }
    }        
    
    //////////////////////////////////////////////
    
  • How to switch from one text to another according to time with the Geomerative library?!

    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(); 
             }
            }
            //////////////////////////////////////////////
    
  • Multiple videos smoothness - threaded playback

    Not sure if doing this through a different thread will help. If you are loading the videos, I would say that assigning the videos, the way you do, should work, assuming your computer can handle loading these many videos.

    I have to say I am not sure your approach works at the end. You are assigning VideoM objects from your video list but I don't think you are ensuring the same video is not picked. Why is this important? Well, because you are calling jump(). If two VideoM objects are handling the same video, you are calling jump on the same handle. it is very likely only the last jump is applied and both handles would display the same video.

    I have to say your code comments are missing? It is hard to understand what you are trying to accomplish in certain parts of your code. Adding comments would help. Also, the name of your arrays are not the best. For this bit of code, the array functionality is lost between the lines. Using better names like masterVideolist would make your code easier to follow.

    I have two questions:
    1. When the timer ends, do you change one video or all the videos?
    2. The display function manages some tinting. What does it do? I can see the alphai counter going up and down but I didn't understand what you want to do.

    I have added some code below but it is not a solution. I just want to capture some changes I did and I will change it as soon as you answer my questions.

    Kf

    import processing.video.*;
    
    final int NSHOWVIDEOS=5;
    
    File path; 
    String[] files;
    int numfiles = 0;
    int timer = -5000;
    int tcontrol= 2000;
    
    boolean bStop, bColor=true;
    boolean bSave=false, bVidO=false;
    
    
    VideoM[] v = new VideoM[NSHOWVIDEOS];
    Movie[] videoStack;
    
    void setup() {
      size(1920, 1080);
      frameRate(60);
      files = files(); 
      numfiles = files.length;
      if (numfiles>11) numfiles=11;
    
      loadvideos();  //Inits videoStack
    
      for (int i = 0; i < NSHOWVIDEOS; i++) {
        v[i] = new VideoM(i);
      }
    }
    
    
    void draw() {
    
      background(0);
      for (int i = 0; i <NSHOWVIDEOS; i++) {
        v[i].display();
      }
    
      if ((millis() - timer) > tcontrol) {
        thread("newvideo");   
        timer = millis();
        tcontrol= int(random(2, 6))*1000;
      }
    }
    
    void movieEvent(Movie m) {
      m.read();
    }
    
    
    void keyPressed()
    {
      int k = keyCode;
    
      // reset all videos
      if (key == 'n' || key == 'N') {
        newset();
      }
    }  
    
    
    
    
    //=====================================================
    void newset() {
      for (int i = 0; i < NSHOWVIDEOS; i++) {
        println(i);
        v[i].newvid();
      }
    }
    
    //=====================================================
    void newvideo() {
      int i = int(random(NSHOWVIDEOS));
      //v[i].nuevovid(this);
      v[i].cambiavid();
    }
    
    //=====================================================
    void loadvideos() {
    
      videoStack = new Movie[numfiles];
    
      for (int i=0; i<numfiles; i++) {
        String video= files[i]; //files[int(random(numfiles))];
        videoStack[i] = new Movie(this, video);
        videoStack[i].play();
        videoStack[i].pause();
        println ("Loading ", video);
      }
    }
    
    
    //=====================================================
    // load files in data
    String[] files() {
      // The data path of the folder to look in (write your own)
      java.io.File folder = new java.io.File(dataPath(""));
    
      // let's set a filter (which returns true if file's extension is .jpg)
      java.io.FilenameFilter pngFilter = new java.io.FilenameFilter() {
        public boolean accept(File dir, String name) {
          return name.toLowerCase().endsWith(".mp4");
        }
      };
    
      // list all the folders inside the main directory
      String[] listFolders = folder.list(new java.io.FilenameFilter() {
        public boolean accept(File current, String name) {
          return new File(current, name).isDirectory();
        }
      }
      );
    
      // list the files in the data folder, passing the filter as parameter
      String[] filenames = folder.list(pngFilter);
    
      return(filenames);
    }
    
    
    //=====================================================
    
    class VideoM {
    
      Movie m;
      String video;
    
      int x, y, w, h;
      int alpha;
      int alphai;
      int fadeout=0;
      int idx;
    
      VideoM(int aidx) {
    
        idx=aidx;
        newvid();
    
      }
    
      void newvid() {  
        m=null;
        int j=idx;//int(random(numfiles));
        println("cambio: ", j);
        m = videoStack[j];
        m.loop();
        genera();
        m.jump(random(m.duration())); 
        println(Thread.currentThread());
      }
    
      void genera() {
        x=int(random(50, width/2+width/4)); 
        y=int(random(50, height/2+height/4)); 
        w=int(random(280, 820));
        h=int(w/1.88);
        alpha=int(random(100, 255)); 
        alphai=0;
      }
    
      void display() {
        tint(255, alphai);
        if (fadeout==0) {
          alphai++; 
          if (alphai>alpha) alphai=alpha;
        } else {  
          alphai--; 
          if (alphai<0) {
            alphai=0;
            fadeout=0;
            this.newvid();
          }
        }
    
        if (frameCount > 1) { 
          //image(m, x, y, w, h);
          image(m, x, y);
        }
      } 
    
      void cambiavid() {
        fadeout=1;
      }
    }
    
  • Multiple videos smoothness - threaded playback

    Hello! This script only requires a bunch of .mp4s in the data folder. You'll see a collage of 9 videos (or duplicates) in different positions and transparencies. The thing runs ok but even pre-loading the videos at the beginning every time there's a change/swap in one of the videos (around every 4 seconds) the whole thing freezes for a sec, sometimes (try to use mp4s of different sizes).

    I tried to use the thread() command in the switching of the videos but nothing happened. I put a println to see the thread but alway show the main thread, I really don't know if I'm doing this ok..

    Thanks a LOT for any help!

    import processing.video.*;
    
    File path; 
    String[] files;
    int numfiles = 0;
    int timer = -5000;
    int tcontrol= 2000;
    int numVideos=9;
    
    VideoM[] v = new VideoM[numVideos];
    Movie[] vv;
    
    void setup(){
      size(1920, 1080, P2D);
      frameRate(60);
      files = files(); 
      numfiles = files.length;
      if (numfiles>11) numfiles=11;
      loadvideos();
    
      for(int i = 0;i < numVideos;i++){
         v[i] = new VideoM();
      }
    }
    
    
    void draw() {
    
      background(0);
      for(int i = 0; i <numVideos; i++){
         v[i].display();
      }
    
      if ((millis() - timer) > tcontrol)  {
        thread("newvideo");   
        timer = millis();
        tcontrol= int(random(2,6))*1000; 
    }
    }
    
    
    void loadvideos(){
    
     String video;
     vv = new Movie[numfiles];
    
     for (int i=0; i<numfiles; i++){
       video= files[int(random(numfiles))];
       vv[i] = new Movie(this, video);
       println ("Loading ", video);
     }
    }
    
    class VideoM {
    
     Movie m;
     String video;
    
     int x;
     int y;
     int w;
     int h;
     int alpha;
     int alphai;
     int fadeout=0;
    
     VideoM() {
      genera();
      println(numfiles);
      m = vv[int(random(numfiles)) ];
      m.loop();
      // m.volume(random(0.4,0.6));
      // m.speed(random(0.6,1.0));
      m.jump(random(m.duration()));  
      //m.play(); 
     }
    
     void genera(){
        x=int(random(50, width/2+width/4)); 
        y=int(random(50, height/2+height/4)); 
        w=int(random(280,820));
        h=int(w/1.88);
        alpha=int(random(100,255)); 
        alphai=0; 
     }
    
     void display(){
       tint(255, alphai);
       if (fadeout==0) {
         alphai++; if (alphai>alpha) alphai=alpha;
       } else {  alphai--; if (alphai<0) {alphai=0;fadeout=0;this.newvid();}
         }
    
       if (frameCount > 1) { image(m, x, y, w, h); }
     } 
    
     void cambiavid(){
       fadeout=1;
     }
    
    void newvid() {  
       m=null;
       int j=int(random(numfiles));
       println("cambio: ", j);
       m = vv[j];
       m.loop();
       genera();
       m.jump(random(m.duration())); 
       println(Thread.currentThread());
     }
    }  
    
    void newset(){
      for(int i = 0;i < numVideos;i++){
        println(i);
        v[i].newvid();
      }
    }
    
    void newvideo(){
      int i = int(random(numVideos));
      //v[i].nuevovid(this);
      v[i].cambiavid();
    }
    
    void movieEvent(Movie m) {
      m.read();
    }
    
    boolean bStop,bColor=true;
    boolean bSave=false,bVidO=false;
    void keyPressed()
    {
      int k = keyCode;
    
      // reset all videos
      if (key == 'n' || key == 'N') {
        newset();
        }
    
    }  
    
    
    // load files in data
    
    String[] files(){
    // The data path of the folder to look in (write your own)
    java.io.File folder = new java.io.File(dataPath(""));
    
    // let's set a filter (which returns true if file's extension is .jpg)
    java.io.FilenameFilter pngFilter = new java.io.FilenameFilter() {
      public boolean accept(File dir, String name) {
        return name.toLowerCase().endsWith(".mp4");
      }
    };
    
    // list all the folders inside the main directory
    String[] listFolders = folder.list(new java.io.FilenameFilter() {
      public boolean accept(File current, String name) {
        return new File(current, name).isDirectory();
      }
    });
    
    // list the files in the data folder, passing the filter as parameter
    String[] filenames = folder.list(pngFilter);
    
    return(filenames);
    }
    
  • How to switch from one text to another according to time with the Geomerative library?!

    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);
      }
    }
    
  • How to switch from one text to another according to time with the Geomerative library?!

    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

  • How do I make the timer stop and reset?

    If you hold 'v' (that's like the sixth time I'm saying that), the timer will not increment.

    I think that's good. Normally user should hit v only briefly and not hold it down. When he holds it down, nothing happens until he releases.

    I found out that the player could still move allowing the player to complete the maze in 0:00.

    That is bad.

    I made a new version where inputs checks if v is down, using variable vIsDown

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown=false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown)
        difference = 0;
      else
        difference = ( millis() - count_at_reset ) /1000;
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed) {
        return;
      }
    
      if (vIsDown) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y--;
      }
    
      if (key == 's'||key == 'S') {
        y++;
      }
    
      if (key == 'u'||key == 'U') {
        x--;
      }
    
      if (key == 'i'||key == 'I') {
        x++;
      }
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=true;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    //
    
  • How do I make the timer stop and reset?

    Run the code and press 'v' a few times and also look at the timer. You should see it occasionally increment to 1 right after it resets.

    this formula is better

     difference = ( millis() - count_at_reset ) /1000;
    

    (before we had millis()/1000 - count_at_reset/1000; and millis()/1000 was rounded to an int and therefore lead to this bug)

  • How do I make the timer stop and reset?

    Run the code and press 'v' a few times and also look at the timer. You should see it occasionally increment to 1 right after it resets.

    The problem is still happening and I don't know how to fix this line of code.

    difference = millis()/1000 - count_at_reset/1000;

    There's also another problem. If you hold 'v' (that's like the sixth time I'm saying that), the timer will not increment. At first I thought it wouldn't be a problem, but then I found out that the player could still move allowing the player to complete the maze in 0:00. Could you help me with all of these?

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown=false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown)
        difference = 0;
      else
        difference = millis()/1000 - count_at_reset/1000;
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y--;
      }
    
      if (key == 's'||key == 'S') {
        y++;
      }
    
      if (key == 'u'||key == 'U') {
        x--;
      }
    
      if (key == 'i'||key == 'I') {
        x++;
      }
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=true;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    
  • How do I make the timer stop and reset?

    On keyReleased, you enable the counter back again.

    see variable vIsDown

    also I used text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30); with trim

    /*
     Press 'q' to move up.
     Press 's' to move down.
     Press 'u' to move left.
     Press 'i' to move right.
     Press 'v' to restart.
     Get to the end as fast as possible.
     If you go on to the red areas, you will fail.
     */
    
    // The variable state
    // the constants the variable state can have as values
    final int STATE_NORMAL = 0;  // unique numbers
    final int STATE_FAIL   = 1;
    final int STATE_WON    = 2;
    final int STATE_SLOW   = 3;
    int state = STATE_NORMAL; // The variable state
    
    // other constants  
    final int MIN_DISTA = 3; 
    final int SLOW_TIME = 9*60+59;
    final PVector eggLocation = new PVector(38, 14);
    float x = 10, y = 380;
    
    int difference, sec, count_at_reset, min;
    
    boolean vIsDown=false;
    
    void setup() {
      size(400, 400);
      frameRate(60);
    }
    
    void draw() {
      switch(state) {
    
      case STATE_NORMAL:
        drawForNormal();
        break;
    
      case STATE_FAIL:
        drawForFail();
        break;
    
      case STATE_WON:
        drawForWon();
        break;
    
      case STATE_SLOW:
        drawForSlow();
        break;
    
      default:
        state = STATE_NORMAL;
        println("Error");
        break;
      }
    }
    
    // ----------------------------------------
    // functions called by draw() 
    
    void drawForNormal() {
      background(255, 0, 0);
      fill(0, 255, 255);
      noStroke();
      rect(0, 200, 30, 201);
      rect(30, 200, 320, 30);
      rect(80, 200, 20, -100);
      rect(100, 100, 30, 20);
      rect(130, 100, 20, 50);
      rect(150, 130, 20, 20);
      rect(170, 150, 20, -100);
      rect(170, 50, -50, 20);
      rect(120, 70, -20, -70);
    
      checkBoundaries();
    
      if (vIsDown)
        difference = 0;
      else 
      difference = millis()/1000 - count_at_reset/1000;
    
      if (difference<SLOW_TIME) {
        sec = difference%60;
        min = (difference-sec)/60;
        fill(255);
        textSize(26);
        text(nfs(min, 1, 0)+":"+trim(nfs(sec, 2, 0)), 310, 30);
      } else {
        state = STATE_SLOW;
      }
      // PLAYER
      stroke(0);
      fill(0, 255, 0);
      rect(x, y, 10, 10);
    
      if (y < 1) {
        state=STATE_WON;
      }
    
      inputs();
    
      if (x < 0 ) { 
        x = 0;
      }
    
      if (y > height-10 ) {
        y = height-10;
      }
    
      if (dist(mouseX, mouseY, eggLocation.x, eggLocation.y)< MIN_DISTA) {
        stroke(#F26E72);
        fill(#10FF58);
        rect(368, 92, 76, 165);
        stroke(#12B6F8);
        fill(#46FA47);
        ellipse(82, 78, 71, 71);
        stroke(#EB10BA);
        fill(#87FE65);
        triangle(284, 350, 142, 72, 50, 1);
        stroke(#A4BFC0);
        fill(#86ED91);
        quad(47, 97, 58, 4, 157, 149, 49, 28);
      }
      if (x == 219) {
        stroke(#FF7460); 
        line(196, 3, 45, 7);
      }
    }
    
    void drawForFail() {
      fill(255);
      textSize(140);
      text("FAIL", 60, 370);
      textSize(22);
      text("Press v to replay", 210, 70);
    }
    
    void drawForWon() {
      fill(255);
      textSize(30);
      text("YOU WON\n"
        +sec
        +"\nPress v to reset.", 80, 270);
    }
    
    void drawForSlow() {
      fill(255);
      textSize(130);
      text("SLOW", 40, 370);
      textSize(30);
      text("Try again", 210, 70);
    }
    
    // -----------------------------------------------
    // Tools
    
    void inputs() {
    
      if (!keyPressed) {
        return;
      }
    
      if (key == 'q'||key == 'Q') {
        y--;
      }
    
      if (key == 's'||key == 'S') {
        y++;
      }
    
      if (key == 'u'||key == 'U') {
        x--;
      }
    
      if (key == 'i'||key == 'I') {
        x++;
      }
    }
    
    void keyPressed() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=true;
      }
    }
    
    void keyReleased() {
      if (key == 'v'||key == 'V') {
        reset();
        vIsDown=false;
      }
    }
    
    void checkBoundaries() {
      if (x > 20 && y > 221) {
        state = STATE_FAIL;
      }
    
      if (x > 340 && y < 222 && y > 192) {
        state = STATE_FAIL;
      }
    
      if (x > 180 && y < 200) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 181 && y < 200 && y > 140) {
        state = STATE_FAIL;
      }
    
      if (x > 90 && x < 130 && y < 141 && y > 110) {
        state = STATE_FAIL;
      }
    
      if (x > 110 && x < 181 && y < 50 && y > 0) {
        state = STATE_FAIL;
      }
    
      if (x > -1 && x < 80 && y < 200 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 79 && x < 100 && y < 100 && y > -1) {
        state = STATE_FAIL;
      }
    
      if (x > 99 && x < 170 && y < 100 && y > 60) {
        state = STATE_FAIL;
      }
    
      if (x > 140 && x < 170 && y > 99 && y < 130) {
        state = STATE_FAIL;
      }
    }
    
    void reset() {
      state = STATE_NORMAL;
      count_at_reset = millis();
      x = 10;
      y = 380;
    }
    //
    
  • How do I make the timer stop and reset?

    Run the code and press 'v' a few times and also look at the timer. You should see it occasionally increment to 1 right after it resets.

    that's true.

    millis is counted right from the start, so when you look at this line:

     millis()/1000 - count_at_reset/1000
    

    and millis() is almost dividable by 1000 the first second you expect is almost over in no time