Struggling to implement a pause/delay within my for-loop

Beginner here.

I am developing a program that involves drawing a grid of cells, in a row-by-row fashion. I want the program to draw a row of cells, then pause for a short time (say 1 second) before moving down and drawing the next row, then pause, then the next row, and so on…

For the sake of clarity I have written this simple program to test this method. When I run this code it seems to pause at the very start before doing anything, then it draws all of my rows seemingly instantly. This is not what I want, I need a pause before each row is drawn.

My reasoning behind this code is as follows:

My program comes to my nested for-loop, it enters the “row” loop and waits until frameCount is at a multiple of 60 before entering the “cell” loop, at this point it draws a row of cells almost instantly, then exits the “cell” loop and waits again, then enters and so on until all rows have been drawn.

So it really baffles me why this code isn’t working. I have been messing around with this for well over an hour now and it’s reall frustrating. I have tried similar methods involving millis() and delay() but they are problematic too.

I would be really greatful if someone could give me some pointers here! Thank you

void setup(){
  size(800,800);
  background(0);
  frameRate(60);
}

void draw(){
  
  int delay = 60;
  
  int cellSize = 20;
  int cellNum = width/cellSize;
  int rowNum = height/cellSize;
  
  for(int row = 0; row < rowNum; row++){                              // "row" loop
    if(frameCount % delay == 0){                                      // My delay should occur here
      for(int cell = 0; cell < cellNum; cell++){                      // "cell" loop
        rect(cell * cellSize, row * cellSize, cellSize, cellSize);
      }
    }
  }
}

Sad news: draw() doesn’t update the screen throughout but only once at its end

Hence you cannot see any animation when you use for

Better get rid of the for loop
And program it by using the fact that draw loops automatically 60 times per second

1 Like

That really is sad news. Looks like I am going to have to restart my project from scratch. My whole idea was based around for-loops.

Thank you for the quick reply! I appreciate it. I’ve been pulling my hair out all evening trying to figure this out.

No, don’t rewrite

It’s not much change really

When you init the variables that were for loops variables and say i++; at the end of draw and add some ifs you are almost there

1 Like

The code in my OP is not the actual project itself. Just a really simplified version to make it easier for people to read. My own project is far too long and messy to show here. But I will consider what you are saying and I will try to work around the problem when my mind is fresher. Thanks

@mon I’d second what @Chrisir said. You don’t have to rewrite the whole thing (even if your actual project is more complex). I think you should be able to make some slight changes to the structure of your code using almost the same things you already have with slight modification.

Instead of nesting the for loops, try giving each for loop some sort of conditional, so they only run individually if they meet their condition.

pseudocode:

if (condition 1)
  for (for loop 1)

if (condition 2)
  for (for loop 2)

This way your sketch calls draw( ), gets to the first true conditional and does the first for-loop. It keeps calling draw( ) and the first conditional stays true until eventually the second is also true and it does the second for-loop. Just remember that you need that first one to be true each time draw( ) is called, not just once or it will go away the next time draw( ) is called.

This might also take care of the issue you’ll have running your current conditional:

frameCount starts at 0, and 0 modulo any number greater than 0 is just 0.

So your condition is met that very first frame.

0 % delay == 0

It doesn’t get to frameCount = 1 until after the first draw( ) completes. Instead maybe use a greater or equal?

if (frameCount >= delay)
   for(second for loop)
2 Likes

How about something like this?

int maxIter = 0;

void setup() {
  size(400, 400);
}

void draw() {
  background(200);

  int x = 0;
  for (int i = 0; i < maxIter; i++) {
    rect(x, height/2, 10, 10);
    x += 20;
  }

  if (frameCount % 30 == 0) {
    maxIter++;
  }
}
1 Like

here is my solution to the problem. It just creates a coloumb of squares every dly milliseconds and doesn’t pause the program. Try it!
(its blured if you didn’t want to see it. just press on it to view)

int mL = 0, lastUpdate = 0, dly = 400;

void setup() {
  size(600,600);
}

void draw() {
  background(0);
  for(int i = 0; i < mL; i++) {
    for(int j = 0; j < 10; j++) {
      rect(i*10,j*10,10,10);
    }
  }
  if(lastUpdate + dly < millis()) {
    lastUpdate = millis();
    mL++;
  }
}
1 Like

Thank you all for your help. Reading through each of your approaches has really helped me get a better understanding of Processing and how the draw() method works. The solution I’m working on is similar to @ErraticGenerator and @CodeMasterX. Now its just a matter of implementing this into the giant mess that is my project code. I might share the project on the forum when I’m done.

Thank you all!

2 Likes

@RFullum it won’t let me tag three people in my post so you get a special reply of your own. Thank you!

2 Likes

How to turn a nested for-loop to an animation with two variables

Example with two for-loops:

void setup() {
  // init
  size(800, 800);
} // func 

void draw() { 
  background(255);

  for (int x=0; x < 30; x++) 
    for (int y=0; y < 30; y++)
      ellipse(x*20+10, y*20+10, 19, 19);
} // func 
//


Here the two for-loops are replaced.
draw() loops in itself, here you can see the animation.


// the former for-loop variables become global variables 
int x, y; 

void setup() {
  // init
  size(800, 800);
} // func 

void draw() { 
  ellipse(x*20+10, y*20+10, 19, 19);

  // Former inner for-loop gets incremented : 
  y++; 

  // when the former for-loop y has ended: 
  if (y >= 30) {
    y=0; // reset 
    x++; // increment former outer for-loop

    // when the former for-loop x has ended:
    if (x >= 30) {
      noLoop();
    }
  }
  //
} // func 
//

1 Like

in theory, you can let your sketch run in a secondary thread. The thread would update an image with the output.

The primary Sketch would then display this image. With this (and some timers) you can achieve an animation with for-loops too. But I think the way above (using that draw() is looping) is much easier.

Chrisir

cf. Update screen during draw() without thread? (for recursion though)

1 Like

@Chrisir Thank you for another example. That works nicely and I see you have a delay when it both draws a cell and moves to a new column. I can’t figure out why your second piece of code is causing the delay though, can you explain what is causing the delay?

I’ve been trying to implement the other commenters’ solutions into my project code all day and haven’t had much success. It worked in my simple example but when it came to carrying that over to my project it either seems to not draw any rows > row 0 or it draws them all instantly.

I’m afraid I don’t know what threads are. I’m very new to this

1 Like

I don’t know, maybe it’s just slow.

draw() is only running 60 times per second, maybe that’s it

Did you try my Code within yours?

I understand that yours is fairly complex.

But my code could just work when you remove your for-loop and replace with the section that takes care of x and y in the 2nd code

see Image resize animation and duplication using squareroot size

I made a change to your program and it draws column-by-column… you can adapt it to row-by-row.

You must also consider what to do with cell since it is not in a for loop and will keep increasing.

int cell;

void setup()
  {
  size(800,800);
  background(0);
  frameRate(60);
  }

void draw()
  {
  int delay = 10;
  
  int cellSize = 20;
  int cellNum = width/cellSize;
  int rowNum = height/cellSize;
  
  if(frameCount % delay == 0)
    {
    cell++;
    println(cell);
    }
  
  for(int row = 0; row < rowNum; row++)
    {                              // "row" loop
    //if(frameCount % delay == 0)
      {                                      // My delay should occur here
      //for(int cell = 0; cell < cellNum; cell++)
        {                      // "cell" loop
        rect(cell * cellSize, row * cellSize, cellSize, cellSize);
        }
      }
    }
  }

:)