Let me show you the way I usually do my creative coding.
Can I show you how I make my creative coding work?
Let me show you how I usually do the creative coding.
I usually start with some ideas (mathematical, algorithmic, etc). I never decide what I make at the start.
I started with the idea 'Equal distance angles and radii' this time.
I'll write the 'Processing' example code in this article.
Freely play with the idea.
At first, I play with the idea as I like.
Put circles on the location that calculated with the Perlin noise or just randomly.
Wide interval or narrow interval.
Connecting circles with lines. etc.
Then, I thought it may be interesting if I moved connected circles with the Perlin noise.
Grasp the feeling of interest.
When I feel it may be interesting, I stop free playing and pursue that interest.
I mean play hard toward the interest that I find.
I tried to make an animation of connected circles with the Perlin noise. I changed radius with the Perlin noise like this.
元はこれから始まった。🧐#processing #creativecoding pic.twitter.com/3pMFmD1qaJ
— deconbatch (@deconbatch) October 11, 2020
/**
* How I usually do creative coding.
* An animation of connected circles with the Perlin noise.
*
* @author @deconbatch
* @version 0.1
* @license GPL Version 3 http://www.gnu.org/licenses/
* Processing 3.5.3
* 2020.10.13
*/
void setup() {
size(640, 640);
colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
frameRate(24);
}
void draw() {
int thetaMax = 12;
int radiusMax = 20;
ArrayList<PVector> arcs = new ArrayList<PVector>();
// animation cycle
float frmRatio = map(frameCount % 120, 0, 120, 0.0, TWO_PI);
// calculate the locations with the cyclic Perlin noise
for (int thetaCnt = 0; thetaCnt < thetaMax; thetaCnt++) {
float noiseVal = noise(thetaCnt, 10.0 + 0.5 * cos(frmRatio), 10.0 + 0.5 * sin(frmRatio));
arcs.add(new PVector
(ceil(noiseVal * radiusMax) * min(width, height) * 0.5 / radiusMax,
thetaCnt * TWO_PI / thetaMax
));
}
background(0.0, 0.0, 90.0, 100.0);
translate(width * 0.5, height * 0.5);
stroke(0.0, 0.0, 30.0, 100.0);
// draw lines
noFill();
beginShape();
for (PVector a : arcs) {
vertex(a.x * cos(a.y), a.x * sin(a.y));
}
endShape(CLOSE);
// draw circles
fill(0.0, 0.0, 90.0, 100.0);
for (PVector a : arcs) {
ellipse(a.x * cos(a.y), a.x * sin(a.y), 20.0, 20.0);
}
}
Amusing! I tried to use curveVertex() to connect points smoothly and omitted drawing circles.
Amoeba尊し🦠#processing #creativecoding pic.twitter.com/vSMNzGw0ek
— deconbatch (@deconbatch) October 5, 2020
Amoeba!
Ummm... not bad. But I felt it come to a dead end. So I tried to change the drawing style with the same algorithm.
When I used arc().
機械世界の Amoeba🤖#processing #creativecoding pic.twitter.com/Pr9w4LEH42
— deconbatch (@deconbatch) October 5, 2020
for (PVector a : arcs) {
cnt++;
arc(0.0, 0.0,
a.x, a.x,
a.y, a.y + TWO_PI / thetaMax,
PIE
);
}
Not bad! Not bad! I felt the interest be able to go further now.
I found that the arc() with noFill() and thick strokeWeight() makes a piece of Baumkuchen.
noFill();
strokeWeight(30);
strokeCap(SQUARE);
for (PVector a : arcs) {
cnt++;
arc(0.0, 0.0,
a.x, a.x,
a.y, a.y + TWO_PI / thetaMax
);
}
So I combined the color pieces and made an animation of three primary color mixing.
3原色で元気いっぱいの機械式 Amoeba ⚙️🦠#processing #creativecoding pic.twitter.com/BSGhDT6K1W
— deconbatch (@deconbatch) October 5, 2020
Interesting! I can play with it more!
And I made three different shapes and tried to rotate these.
これが、どこのご家庭にでもある一般的なシリンダー錠の構造をわかりやすく色付けして説明した図ではありません。🔑#processing #creativecoding pic.twitter.com/setAj3ldYN
— deconbatch (@deconbatch) October 6, 2020
回転にイージングをかけてみる。🙂#processing #creativecoding pic.twitter.com/GbRtao3v8B
— deconbatch (@deconbatch) October 6, 2020
And then now, I can see what I want to make.
Decide what I make at last.
After playing with my interest, I wanted to make an animation of rotating color discs.
I thought it must be nice if the rotation had various rotate angles and each discs rotation timings were the same. And mixing the color of each disc would be beautiful.
I made trial product to verify the idea.
一所懸命に鍵を開けようと何度もトライしてる様子。🤨🔐#processing #creativecoding pic.twitter.com/aYH3sgkuNN
— deconbatch (@deconbatch) October 7, 2020
And made a goal!
雰囲気開いた気がする!🔓😀#processing #creativecoding pic.twitter.com/ymKmliXQhY
— deconbatch (@deconbatch) October 7, 2020
That's all.
- I just start with an idea how to calculate. I never start with what I want to make.
- I play with the idea as I like and try to find a special interest.
- When I find a special interest, I pursue that interest.
- Then, I realize what I want to make.
- Make it.
I've been able to make a goal this time. But not always.
If I can not find a special interest, it will come to a dead end and I do not make anything. But I'll satisfy that I played with creative coding much and had fun! 🙂
An example source code of the 'Processing'.
I used Java programming language.
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.
/**
* You Can't Catch Me.
* An animation of rotating discs.
*
* @author @deconbatch
* @version 0.1
* @license GPL Version 3 http://www.gnu.org/licenses/
* Processing 3.5.3
* 2020.10.11
*/
int objMax = 4; // object number
int frmRate = 24; // animation fps
int turnMax = 5; // turn number
float speed = 0.5; // rotation speed : must be > 0.0
float baseHue = random(360.0); // object color
ArrayList<Disc> objs = new ArrayList<Disc>();
void setup() {
size(720, 720);
colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
rectMode(CENTER);
frameRate(frmRate);
// initialize object array
for (int objCnt = 0; objCnt < objMax; objCnt++) {
objs.add(new Disc());
}
}
void draw() {
if (frameCount > frmRate * turnMax / speed) {
exit();
}
background(0.0, 0.0, 90.0, 100.0);
translate(width * 0.5, height * 0.5);
noFill();
for (int objCnt = 0; objCnt < objMax; objCnt++) {
// reset object rotate information
if (!objs.get(objCnt).isRotating()) {
if (frameCount >= frmRate * (turnMax - 1) / speed) {
objs.get(objCnt).rewind(frmRate, speed);
} else {
if (random(1.0) < 0.5) {
objs.get(objCnt).setRotation(frmRate, speed);
}
}
}
// draw object
blendMode(SUBTRACT);
stroke((baseHue + objCnt * 20.0) % 360.0, 90.0, 60.0, 100.0);
pushMatrix();
objs.get(objCnt).rotates();
objs.get(objCnt).draws();
popMatrix();
}
blendMode(BLEND);
casing();
saveFrame("frames/" + String.format("%04d", frameCount) + ".png");
}
/**
* casing : draw fancy casing
*/
public void casing() {
fill(0.0, 0.0, 0.0, 0.0);
strokeWeight(30.0);
stroke(0.0, 0.0, 30.0, 100.0);
rect(0.0, 0.0, width, height);
strokeWeight(28.0);
stroke(0.0, 0.0, 100.0, 100.0);
rect(0.0, 0.0, width, height);
}
/**
* Disc
* holds disc information and control rotation and drawing
*
*/
class Disc {
int arcDiv = 8;
int radiusDiv = 5;
ArrayList<PVector> arcs;
int rotateUnit;
int rotateFrmStart;
int rotateFrmEnd;
float baseRotation;
Disc() {
baseRotation = 0.0;
// failsafe
rotateUnit = 0;
rotateFrmStart = 0;
rotateFrmEnd = 0;
arcs = new ArrayList<PVector>();
for (int arcCnt = 0; arcCnt < arcDiv; arcCnt++) {
arcs.add(new PVector
(
floor(random(radiusDiv * 0.3, radiusDiv)) * min(width, height) * 0.5 / radiusDiv,
arcCnt * TWO_PI / arcDiv
));
}
}
/**
* rewind :
* @param _frmRate : frame rate(fps)
* @param _speed : disc rotate speed
*/
public void rewind(int _frmRate, float _speed) {
float signBaseRot = baseRotation / abs(baseRotation);
float rewindTheta = (abs(baseRotation) > PI) ? signBaseRot * (abs(baseRotation) - TWO_PI) : baseRotation;
rotateUnit = -round(rewindTheta * arcDiv / TWO_PI);
rotateFrmStart = frameCount;
rotateFrmEnd = floor(rotateFrmStart + _frmRate / ((_speed <= 0.0) ? 1.0 : _speed));
}
/**
* setRotation :
* @param _frmRate : frame rate(fps)
* @param _speed : disc rotate speed
*/
public void setRotation(int _frmRate, float _speed) {
rotateUnit = round(random(-arcDiv, arcDiv) * 0.5);
rotateFrmStart = frameCount;
rotateFrmEnd = floor(rotateFrmStart + _frmRate / ((_speed <= 0.0) ? 1.0 : _speed));
}
/**
* rotates : rotate disc
*/
public void rotates() {
if (isRotating()) {
if (frameCount == rotateFrmEnd) {
baseRotation += rotateUnit * TWO_PI / arcDiv;
baseRotation %= TWO_PI;
} else {
float frmRatio = map(frameCount, rotateFrmStart, rotateFrmEnd, 0.0, 1.0);
float easeRatio = InOutCubic(frmRatio);
rotate(rotateUnit * easeRatio * TWO_PI / arcDiv);
}
}
rotate(baseRotation);
}
/**
* draws : draw disc with arc()
*/
public void draws() {
noFill();
strokeCap(SQUARE);
for (int i = 0; i < arcs.size(); i++) {
PVector a = arcs.get(i);
PVector b = arcs.get((i + 1) % arcs.size());
float w = constrain(abs(a.x - b.x), 0.0, a.x);
float r = a.x + w * 0.5;
if (w != 0.0) {
strokeWeight(w);
arc(
0.0, 0.0,
r, r,
a.y, (a.y < b.y) ? b.y : b.y + TWO_PI
);
}
}
}
/**
* isRotating
* @return : rotating = true, not rotating = false
*/
public Boolean isRotating() {
return (frameCount > rotateFrmEnd) ? false : true;
}
/**
* easeInOutCubic easing function.
* @param _t : 0.0 - 1.0 : linear value.
* @return float : 0.0 - 1.0 : eased value.
*/
private float InOutCubic(float _t) {
_t *= 2.0;
if (_t < 1.0) {
return pow(_t, 3) / 2.0;
}
_t -= 2.0;
return (pow(_t, 3) + 2.0) / 2.0;
}
}
/*
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/>
*/
Thanks for this, it was really interesting!
I thank you for reading! 🙂