Flow – GIF

Flow - Sakura Version

My mind process for this project: gif -> looping -> continuity -> time? -> something smooth -> curves? -> water -> flow
In the beginning, in my mind there were two paths for me to take – make something cool-looking/trippy that’s very math oriented, or make something nice to look at/aesthetically appealing. I was a bit lost on the former, so I went with the latter. I wanted something I wouldn’t mind staring at for a few minutes straight, so I ended up with this. I incorporated a lot of random factors so I wouldn’t mind staring at it for a few minutes straight multiple times. I think I invested too much time into trying to make it look pretty when I should have been using that time to try to figure out some cool mathy thing I could incorporate. Oh well, at least I’m happy with the outcome. Enjoyed this project. Will probably want to make another one soon/later.

This was a really quick idea sketch. The lines are really light…

2013-09-11 23.10.12

Anyway, here’s the program. There is a lot of randomness involved, so each time you load it, you’re going to get something noticeably different. Enjoy!

 int     nFramesInLoop = 300;
int     nElapsedFrames;
boolean bRecording; 

ArrayList allPaths = new ArrayList();
PImage object;
PImage noncomformity;

void setup() {
  size (300, 150); 
  bRecording = false;
  nElapsedFrames = 0; 

  int which = int(random(3));
  boolean frog = false;
  //Randomly choose 1 out of 3 available themes
  //and load image accordingly
  if (which==0) {
    object = loadImage("sakura_flower.png");
  else if (which==1) {
    object = loadImage("maple_leaf.png");
  else {
    object = loadImage("lily_pad.png");
    int temp = int(random(2));
    if (temp==1) {
      frog = true;
      noncomformity = loadImage("lily_pad_frog.png");

  //Create individual Path objects and append to global ArrayList
  for (int i=0; i<9; i++) {
    Path p = new Path();
    //Last object has chance to be a frog
    if (i==8 && frog==true){

void keyPressed() {
  bRecording = true;
  nElapsedFrames = 0; 

void draw() {
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } else {
    percentCompleteFraction = (float) (frameCount % nFramesInLoop) / (float)nFramesInLoop;
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    saveFrame("output/myname-loop-" + nf(nElapsedFrames,4) + ".png");
    if (nElapsedFrames > (nFramesInLoop+1)) {
      bRecording = false;

void renderMyDesign(float percent) {
  fill(160, 200, 255, 80);
  rect(0, 0, width, height);

  int n = allPaths.size();

  //Draw background bezier curves first
  for (int i=0; i1) t-=1;
    float thickPercent = sin(2.0*t*TWO_PI);
    float thickness = map(thickPercent,-1,1,thickness1,thickness2);
    stroke(160, 200, 255, 80);
    bezier(x1, y1, cpx1, cpy1, cpx2, cpy2, x2, y2);

  //Draw moving object
  void drawObject(float percent) {
    //Make sure object is correct size before drawing
    ownLook.resize(int(size)*2, int(size)*2);
    //Object starts at random point on curve w/ random rotation
    float t = startT+percent;
    if (t>1) t-=1;
    float x = map(t*width,0,width,x1,x2);
    float y = bezierPoint(y1, cpy1, cpy2, y2, t);

    float cx = x+(size/2);
    float cy = y+(size/2);

    //Draw the object
    translate(cx, cy);
    float angle = (t)*TWO_PI*rotation;
    image(ownLook, -size, -size);    
  //Change the images of moving object
  void changeLook(PImage change){
    ownLook = change;

Comments are closed.