How I made this creative coding animation of a strange kind of node garden.

It's an animation of a strange kind of Node Garden.

It's an animation of a strange kind of Node Garden.


 

It's a creative coding animation made with the 'Processing' programming language. It produces an animation of the simple node garden image morphing to another node garden.

 

The ordinary Node Garden you see a lot.

You may have seen creative coding using the node garden technique like this. Randomly located nodes, and lines that are determined with distance.

 if (dist(xa, ya, xb, yb) < 100) {
   line(xa, ya, xb, yb);
 }
Randomly located nodes example image 01.
Randomly located nodes example image 02.

It's not bad. But it tends to be a too complex and confusing look.

 

Make it simple.

It looks simple if you locate nodes on the grid.

 pvs.push(createVector(
   floor(random(1.0, 10.0)) / 10,
   floor(random(1.0, 10.0)) / 10
 ));
Nodes on the grid example image 01.
Nodes on the grid example image 02.

 

And more, you can draw lines not by these distance but by x-y axis.

 if (xa == xb || ya == yb) {
   line(xa, ya, xb, yb);
 }
Drawing lines by x-y axis example image 01.
Drawing lines by x-y axis example image 02.

 

Follow your interest.

It creates interesting results. I added code to change the node size by the line count.

Change node size example image 01.
Change node size example image 02.

 

Then, let it move!

 // morphing
 float xF = _to.get(f).x * _rate + _from.get(f).x * (1.0 - _rate);
 float yF = _to.get(f).y * _rate + _from.get(f).y * (1.0 - _rate);

Morphing example image 01.

 

That's it! This is the fun of creative coding!

 







An example code of the 'Processing'.

This code does not display any images on the screen but generates image files in frames directory. You can make an animation with these files.

Please feel free to use this example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor. 😀



/**
 * Johnny on the Monorail.
 * It's an animation of a strange kind of Node Garden.
 * 
 * @author @deconbatch
 * @version 0.1
 * Processing 3.5.3
 * 2020.08.25
 */

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  rectMode(CENTER);
  smooth();
  noLoop();
}

void draw() {

  int nodeCnt  = 30;
  int frmMax   = 24 * 12; // 24fps x 12sec
  int frmMorph = 24 * 4;  // morphing duration frames

  ArrayList<PVector> nodesFrom = new ArrayList<PVector>();
  ArrayList<PVector> nodesTo = setNodes(nodeCnt);

  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {

    float easeRatio = InFourthPow(map(frmCnt % frmMorph, 0, frmMorph - 1, 0.0, 1.0));
      
    // copy to -> from
    if (frmCnt % frmMorph == 0) {
      nodesFrom = new ArrayList<PVector>(nodesTo);
      nodesTo = setNodes(nodeCnt);
    }
 
    blendMode(BLEND);
    background(0.0, 0.0, 90.0, 100.0);

    fill(0.0, 0.0, 90.0, 100.0);
    stroke(0.0, 0.0, 10.0, 100.0);
    strokeWeight(2.0);
    construct(nodesFrom, nodesTo, easeRatio);

    blendMode(BLEND);
    casing();

    saveFrame("frames/" + String.format("%04d", frmCnt) + ".png");

  }
  exit();
}

/**
 * setNodes : set nodes to draw.
 * @param  _cnt  any : node count.
 * @return           : nodes in ArrayList<PVector>.
 */
private ArrayList<PVector> setNodes(int _cnt) {
  ArrayList<PVector> n = new ArrayList<PVector>();
  for (int i = 0; i < _cnt; i++) {
    n.add(new PVector(
                      floor(random(2.0, 9.0)) / 10.0,
                      floor(random(2.0, 9.0)) / 10.0
                      ));
  }
  return n;
}

/**
 * construct : calculate morphing location and draw.
 * @param  _from : nodes of start location of morphing.
 * @param  _to   : nodes of end location of morphing.
 * @param  _rate 0.0 - 1.0 : start(0.0) - end(1.0)
 */
private void construct(ArrayList<PVector> _from, ArrayList<PVector> _to, float _rate) {
  for (int f = 0; f < _from.size() - 1; f++) {
    int cons = 0;
    float xF = _to.get(f).x * _rate + _from.get(f).x * (1.0 - _rate);
    float yF = _to.get(f).y * _rate + _from.get(f).y * (1.0 - _rate);
    for (int t = f + 1; t < _to.size(); t++) {
      float xT = _to.get(t).x * _rate + _from.get(t).x * (1.0 - _rate);
      float yT = _to.get(t).y * _rate + _from.get(t).y * (1.0 - _rate);
      if (abs(xF - xT) < 0.01 || abs(yF - yT) < 0.01) {
        line(xF * width, yF * height, xT * width, yT * height);
        cons++;
      }
    }
    if (cons % 2 == 0) {
      rect(xF * width, yF * height, cons * 5.0, cons * 5.0, 4);
    } else {
      ellipse(xF * width, yF * height, cons * 5.0, cons * 5.0);
    }
  }
}

/**
 * InFourthPow : easing function.
 * @param  _t    0.0 - 1.0 : linear value.
 * @return       0.0 - 1.0 : eased value.
 */
private float InFourthPow(float _t) {
  return 1.0 - pow(1.0 - _t, 4);
}

/**
 * casing : draw fancy casing
 */
public void casing() {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(width * 0.5, height * 0.5, width, height);
  strokeWeight(28.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(width * 0.5, height * 0.5, width, height);
}


/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/



 

 Yet another example images.

It's an animation of a strange kind of Node Garden.

It's an animation of a strange kind of Node Garden.

 

Next Post Previous Post
No Comment
Add Comment
comment url