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);
}
}
}
}
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?
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)
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.
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
//
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 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