Sequence of actions from array

Howdy!

I want to create a sequence of events as determined by an array, but for some reason, only the last element of the array is accounted for.

Also, I would like the actions to occur with a slight delay with respect to each other. The delay() function would not work as it would stop all the program, while I would need the program to keep on running during the delay.

Below is some code to make a particular color square according to the integer stored in an array. The only square that seems to appear is the one specific to the last element of the array.

Ideally, what I would want is for every square, as determined by each element in the array, to appear sequentially, with something like a one second delay between each square’s apparition. The simplified sketch below could employ the delay() function, but I made it as an illustration of a problem in a more complex sketch, in which they delay actions should occur without interfering with all other aspects of the program running in tandem.

int[] array = new int[5];

void setup() {
  size(600, 600);
  background(128);
  for (int i = 0; i < array.length; i++) {
    array[i] = int(random(4));
  }
  println(array);
}

void draw() {
  //background(128);
}

void keyPressed() {
  for (int i = 0; i < array.length; i++) {
    if (array[i] == 0) {
      fill(0);
      rect(200, 200, 100, 100);
    }
    if (array[i] == 1) { 
      delay(300);
      fill(255, 0, 0);
      rect(200, 200, 100, 100);
    }   
    if (array[i] == 2) {
      fill(0, 255, 0);
      rect(200, 200, 100, 100);
    }
    if (array[i] == 3) {
      fill(0, 0, 255);
      rect(200, 200, 100, 100);
    }
    if (array[i] == 4) {
      fill(255);
      rect(200, 200, 100, 100);
    }
  }
}

Thanks for any help.

1 Like

Here is my idea

int[] array = new int[5];
int actionCounter = 0; 
int timer; 

void setup() {
  size(600, 600);
  background(128);
  for (int i = 0; i < array.length; i++) {
    array[i] = int(random(4));
  }
  println(array);

  timer = millis();
}

void draw() {
  background(128);
  showAction() ; 

  if (millis()-timer >= 1100) { 
    actionCounter++;
    timer = millis();
  }
}

void showAction() {
  if (actionCounter == 0) {
    fill(0);
    rect(200, 200, 100, 100);
  } else if (actionCounter == 1) { 
    // delay(300);
    fill(255, 0, 0);
    rect(200, 200, 100, 100);
  } else if (actionCounter == 2) {
    fill(0, 255, 0);
    rect(200, 200, 100, 100);
  } else if (actionCounter == 3) {
    fill(0, 0, 255);
    rect(200, 200, 100, 100);
  } else if (actionCounter == 4) {
    fill(255);
    rect(270, 200, 100, 100);
  }//if
}
2 Likes

I started working this up before the last post … so i’ll go ahead and share this method as well.

using millis() like in @Chrisir example is more accurate than this method btw.

ArrayList<ColorSwatch> colorSwatches = new ArrayList();
color[] cols = {#22223B, #4A4E69, #9A8C98, #C9ADA7, #F2E9E4};
int idx, counter = 0;

void setup() {
  size(600, 600);
  rectMode(CENTER);
  for (int i = 0; i < 5; i++) {
    colorSwatches.add(new ColorSwatch(new PVector(width*0.5, height*0.5), cols[int(random(4))], 100));
  }
}

void draw() {
  background(13, 17, 21);
  textSize(100);
  updateSwatch();
  colorSwatches.get(idx).display();

  counter++;
}

void updateSwatch() {
  if (counter % 100 == 0) {
    if (idx >=4) {
      idx = 0;
      counter = 0;
    } else {
      idx++;
    }
  }
}

class ColorSwatch {
  PVector pos;
  color col;
  int scl;

  ColorSwatch(PVector p, color c, int s) {
    pos = p;
    col = c;
    scl = s;
  }

  void display() {
    pushStyle();
    noStroke();
    fill(col);
    rect(pos.x, pos.y, scl, scl);
    popStyle();
  }
}

2 Likes

Hello,

Here is an example using frameCount and case statements:
https://discourse.processing.org/t/animation-that-transitions-using-framecount/15378

https://processing.org/reference/case.html
https://processing.org/reference/switch.html
https://processing.org/reference/draw_.html
https://processing.org/reference/frameRate_.html
https://processing.org/reference/frameCount.html

:)

2 Likes

Thanks to all of you guys!
@Chrisir Your sketch gave me the solution. You misunderstood what I wanted: not the colors to appear one by one as listed, but for them to appear one by one in accordance to the array of random values. I just had to do a minor modification on your sketch, and found the solution I was looking for. But I couldn’t have done it without your help.

int[] array = new int[5];
int actionCounter = 0; 
int timer; 
int j;

void setup() {
  size(600, 600);
  background(128);
  for (int i = 0; i < array.length; i++) {
    array[i] = int(random(4));
  }
  println(array);

  timer = millis();
}

void draw() {
  background(128);
  showAction() ; 

  if (millis()-timer >= 1100) { 
    actionCounter++;
    timer = millis();
  }
}

void showAction() {
  if (actionCounter == 0) {
    j = 0;
    setColor();
    rect(200, 200, 100, 100);
  } else if (actionCounter == 1) { 
    j = 1;
    setColor();
    rect(200, 200, 100, 100);
  } else if (actionCounter == 2) {
    j = 2;
    setColor();
    rect(200, 200, 100, 100);
  } else if (actionCounter == 3) {
    j = 3;
    setColor();
    rect(200, 200, 100, 100);
  } else if (actionCounter == 4) {
    j = 4;
    setColor();
    rect(200, 200, 100, 100);
  }
}

void setColor() {

  if (array[j] == 0) {
    fill(0);
    rect(200, 200, 100, 100);
  }
  if (array[j] == 1) { 
    fill(255, 0, 0);
    rect(200, 200, 100, 100);
  }   
  if (array[j] == 2) {
    fill(0, 255, 0);
    rect(200, 200, 100, 100);
  }
  if (array[j] == 3) {
    fill(0, 0, 255);
    rect(200, 200, 100, 100);
  }
  if (array[j] == 4) {
    fill(255);
    rect(200, 200, 100, 100);
  }
}
3 Likes

Ways to approach this depend on on if you want things moving, or shown / hidden, or colored, et cetera.

A generic way to hand this is a set of event commands as data. So here is an event processor that draws colored squares:

void eventSquare(color c) {
  fill(c);
  rect(200, 200, 100, 100);
}

Now if we have set of times and colors, like this:

color / frame to display
0 / 60
127 / 120
255 / 180

Our goal is to save them as data, then check our data and if the frame matches, call the event action.

There are many ways to save them as data. We could use a simple array:

int[][] events = new int[3][];
events[0] = new int[] { color(0), 60 };
events[1] = new int[] { color(128), 120 };
events[2] = new int[] { color(255), 180 };

…or an ArrayList, or custom classes. But no matter what, at draw time we check, and if the frameCount matches, we pass the color to our function:

for(int i=0; i<events.length; i++) {
  if(events[i][1] == frameCount) {
    eventSquare(events[i][0]);
  }
}

Here it is playing the timed animation when you put it all together:

int[][] events = new int[3][];

void setup() {
  size(400, 400);
  events[0] = new int[] { color(0), 60 };
  events[1] = new int[] { color(128), 120 };
  events[2] = new int[] { color(255), 180 };
}

void draw() {
  for (int i=0; i<events.length; i++) {
    if (events[i][1] == frameCount) {
      eventSquare(events[i][0]);
    }
  }
}

void eventSquare(color c) {
  fill(c);
  rect(200, 200, 100, 100);
}

So, in general, don’t pass the time to your drawing function and then decide on the time using if / else or switch. Instead, loop over your time data and check for matches. After you decide what to draw, then call the drawing function with the appropriate arguments.

2 Likes