Creative coding animation of the flower garden
The spinning ellipse animation with circle packing.
It's a creative coding animation made with Processing. It draws the spinning wheel located with circle packing.
I took part in an event 'Daily Coding Challenge' that was held by Processing Community Japan. And I made an animation about a theme 'ま' 丸み (Roundness). It draws a sphere look with a rectangle.
Daily Coding Challenge' Processing Community Japan.
📅オンライン企画第一弾として、Processing Community Japan ではデイリーコーディングチャレンジを始めます📅— PCD @ Tokyo (@PCD_Tokyo) March 30, 2020
4/1から5/14まで、毎日50音順のお題に沿ってみんなでコーディングをしてコミュニティを盛り上げましょう!Processing / p5.js に限らずどのツールも歓迎ですhttps://t.co/zFTOI6okkJ
Roundness.
— deconbatch (@deconbatch) May 1, 2020
I proceeded to draw rotating fans with an ellipse. And I use the Circle Packing method to locate the fans.
Rotating fans with an ellipse.
— deconbatch (@deconbatch) May 2, 2020
Circle packing location.
— deconbatch (@deconbatch) May 2, 2020
For cyclic animation, I made it start and end with circle not ellipse.
Example code of 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 Processing example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.
/**
* Spin the Wheel.
* the rotating fans located with circle packing.
*
* Processing 3.5.3
* @author @deconbatch
* @version 0.1
* created 0.1 2020.05.03
*/
void setup() {
size(720, 480);
colorMode(HSB, 360, 100, 100, 100);
smooth();
noLoop();
}
void draw() {
int frmMax = 24 * 10; // for 24fps x 10s animation
ArrayList<Fan> fans = circlePacking();
background(0.0, 0.0, 100.0, 100.0);
for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
float frmRatio = map(frmCnt, 0, frmMax, 0.0, 1.0);
// after image effect
noStroke();
fill(0.0, 0.0, 100.0, 100.0 - 90.0 * sin(PI * frmRatio));
rect(0.0, 0.0, width, height);
// draw fans
for (Fan f : fans) {
f.draw(sin(PI * easeInOutCubic(frmRatio)));
}
casing();
saveFrame("frames/" + String.format("%04d", frmCnt) + ".png");
}
exit();
}
/**
* circlePacking : locate fans with the Circle Packing method.
*/
ArrayList<Fan> circlePacking() {
int tryMax = 10000; // a trying count to add and grow fans.
float gap = 12.0; // gap between fans
float margin = 50.0;
float baseHue = random(360.0);
ArrayList<Fan> fans = new ArrayList<Fan>();
for (int tryCnt = 0; tryCnt < tryMax; tryCnt++) {
float fX = random(margin, width - margin);
float fY = random(margin, height - margin);
// add new fan
boolean inner = false;
for (Fan f : fans) {
if (dist(fX, fY, f.x, f.y) < f.r + gap) {
inner = true;
break;
}
}
if (!inner) {
fans.add(new Fan(fX, fY, baseHue + noise(fX * 0.01, fY * 0.01) * 240.0));
}
// grow fans
for (Fan fThis : fans) {
boolean collision = false;
for (Fan fThat : fans) {
if (fThis != fThat) {
if (dist(fThis.x, fThis.y, fThat.x, fThat.y) < (fThis.r + fThat.r) * 0.5 + gap) {
collision = true;
break;
}
}
}
if (!collision) {
fThis.grow();
}
}
}
return fans;
}
/**
* casing : draw fancy casing.
*/
private void casing() {
fill(0.0, 0.0, 0.0, 0.0);
strokeWeight(30.0);
stroke(0.0, 0.0, 0.0, 100.0);
rect(0.0, 0.0, width, height);
strokeWeight(26.0);
stroke(0.0, 0.0, 100.0, 100.0);
rect(0.0, 0.0, width, height);
}
/**
* easeInOutCubic easing function.
* @param t 0.0 - 1.0 : linear value.
* @return float 0.0 - 1.0 : eased value.
*/
private float easeInOutCubic(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;
}
/**
* Fan : draw and hold location, size and color.
*/
public class Fan {
public float x, y; // coordinate of fan
public float r; // radius
private float elpVal; // ellipticity
private float hueVal; // hue value of fan
private float satVal; // saturation value of fan
private float rotVal; // rotation radians
private float incRot; // increment value of radians
Fan(float _x, float _y, float _c) {
x = _x;
y = _y;
r = 10.0; // initial radius of the fan
elpVal = random(0.1, 0.5);
hueVal = _c;
satVal = random(40.0, 60.0);
rotVal = 0.0;
incRot = random(0.1, 1.0) * HALF_PI;
}
public void grow() {
r++;
}
public void draw(float _rate) {
float sigmoid = 2.0 / (1.0 + exp(-10.0 * _rate)) - 1.0;
rotVal += incRot * _rate;
noFill();
strokeWeight(map(sigmoid, 0.0, 1.0, 10.0, 2.0));
stroke(hueVal % 360.0, satVal, 80.0, 100.0);
pushMatrix();
translate(x, y);
rotate(rotVal);
ellipse(0.0, 0.0, r, map(sigmoid, 0.0, 1.0, r, r * elpVal));
popMatrix();
}
}
/*
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 image.