Time based pattern


#1

I’m still awaiting a bright soul to help me understand this aspect of coding*Hello all, we are currently working on a time-based pattern project for class but i’ve manage to hit a wall working on my code. I am new to working in the program so i’m a tad confused.

  1. I would like to make it to where my animation starts at the initial press of the mouse then the ellipse changes/transitions color if the mouse button is held.
  2. I would like to have more than just one ellipse traveling on my sin wave!

I greatly appreciate any help or explanations given!

float rad;
float xOrigin, yOrigin;
float yPos;
boolean toLeft;

void setup() {
size(500, 500);
rad = 50;
yOrigin = height/2;
toLeft = false;
}

void draw() {
background(0);
noStroke();

yPos =cos(frameCount * 0.15) * rad;
ellipse (xOrigin, yOrigin + yPos, 20, 20);

if (toLeft==false) {
xOrigin = xOrigin + 5;
if (xOrigin > 500) {
toLeft = true;
}
}

else {
xOrigin = xOrigin - 5;
if (xOrigin < 0) {
toLeft = false;
}
}
}


#2
  1. You want “more than one” of a thing? Then immediately your brain should scream at you: “WRITE A CLASS FOR THAT OBJECT!” In this case, you want to have more than one sin-wave-ellipse, so write a class for that object!
class WaveBall {
}

Now you already have one working. In fact, all your variables and drawing exist to draw one of these things already. So it is easy to copy what you already have into this class.

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15) * rad;
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall wb0;

void setup() {
  size(500, 500);
  wb0 = new WaveBall();
}

void draw() {
  background(0);
  wb0.draw();
}

Amazing. Now to have two of them, look what changes:

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15) * rad;
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall wb0;
WaveBall wb1;


void setup() {
  size(500, 500);
  wb0 = new WaveBall();
  wb1 = new WaveBall();
}

void draw() {
  background(0);
  wb0.draw();
  wb1.draw();
}

Great! Now there are two of them. Except there aren’t because they are both in the same place. Why? Because both of their positions are the same, and remain the same. We need to make some changes to this object that allows them to be at different positions.

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
    xOrigin = random(width);
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15) * rad;
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall wb0;
WaveBall wb1;


void setup() {
  size(500, 500);
  wb0 = new WaveBall();
  wb1 = new WaveBall();
}

void draw() {
  background(0);
  wb0.draw();
  wb1.draw();
}

Notice that this is a one line change. WaveBalls now have different starting xOrigin positions.


#3

this makes quite a lot more sense. I greatly appreciate the help here. Now all I need to do is tell the animation to start with the mouseClicked() function. I know the function is added after the draw because without it the code is only run once and then stops listening for events but im unsure specifically as to where after the draw function it goes.


#4

Now we want 100 of them.

We could start wriitng this out…

WaveBall wb0;
WaveBall wb1;
WaveBall wb2;
WaveBall wb3;
WaveBall wb4;

But this is STUPID! There must be a better way, right? Well there is! You can put these objects in an ARRAY.

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
    xOrigin = random(width);
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15) * rad;
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall[] wbs;

void setup() {
  size(500, 500);
  wbs = new WaveBall[25];
  for( int i = 0; i < wbs.length; i++) wbs[i] = new WaveBall();
}

void draw() {
  background(0);
  for( int i = 0; i < wbs.length; i++) wbs[i].draw();
}

Great! Now there are many of them. but they all oscillate the same. We should add an oscillation offset next:

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  float osc_offset = random(TWO_PI);
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
    xOrigin = random(width);
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15 + osc_offset) * rad;
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall[] wbs;

void setup() {
  size(500, 500);
  wbs = new WaveBall[25];
  for( int i = 0; i < wbs.length; i++) wbs[i] = new WaveBall();
}

void draw() {
  background(0);
  for( int i = 0; i < wbs.length; i++) wbs[i].draw();
}

Notice that with the addition of TWO LINES OF CODE, I have added this oscilation offset for EVERY WaveBall object! The power!

  1. You want to goof about with colors? Okay. First, let’s give each WaveBall it’s own color:
class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  float osc_offset = random(TWO_PI);
  color c;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
    xOrigin = random(width);
    c = color( random(255), random(255), random(255));
  }
  void draw() {
    noStroke();

    yPos =cos(frameCount * 0.15 + osc_offset) * rad;
    fill(c);
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall[] wbs;

void setup() {
  size(500, 500);
  wbs = new WaveBall[25];
  for ( int i = 0; i < wbs.length; i++) wbs[i] = new WaveBall();
}

void draw() {
  background(0);
  for ( int i = 0; i < wbs.length; i++) wbs[i].draw();
}

That works.


Animation starting on mousepressed? Add a boolean that tracks if the mouse has been pressed yet, and use it to not draw the balls:

class WaveBall {
  float rad;
  float xOrigin, yOrigin;
  float yPos;
  boolean toLeft;
  float osc_offset = random(TWO_PI);
  color c;
  WaveBall() {
    rad = 50;
    yOrigin = height/2;
    toLeft = false;
    xOrigin = random(width);
    c = color( random(255), random(255), random(255));
  }
  void draw() {
    if( !was_pressed ) return;
    noStroke();

    yPos =cos(frameCount * 0.15 + osc_offset) * rad;
    fill(c);
    ellipse (xOrigin, yOrigin + yPos, 20, 20);

    if (toLeft==false) {
      xOrigin = xOrigin + 5;
      if (xOrigin > 500) {
        toLeft = true;
      }
    } else {
      xOrigin = xOrigin - 5;
      if (xOrigin < 0) {
        toLeft = false;
      }
    }
  }
}

WaveBall[] wbs;
boolean was_pressed;

void setup() {
  size(500, 500);
  wbs = new WaveBall[25];
  for ( int i = 0; i < wbs.length; i++) wbs[i] = new WaveBall();
  was_pressed = false;
}

void draw() {
  background(0);
  for ( int i = 0; i < wbs.length; i++) wbs[i].draw();
}

void mousePressed(){
  was_pressed = true;
}

#5

You have been HUGE help with this weeks material. Thank you for helping me to further understand Processing!