The simple creative coding animation with a sine curve
Captivated by the Sine Wave
This creative coding piece, titled "Listening Wind," was crafted using Processing. It’s an exploration of rhythmic, cyclic motion achieved through the mathematical elegance of sine curves and easing functions.
Related Work:
Fading Like a Flower.
The movement mimics ribbons swaying in a gentle breeze. Note that this script is optimized for offline rendering; rather than rendering a real-time preview, it exports high-quality PNG frames that can be compiled into a smooth video.
Digging into the Source Code
Feel free to use or modify this Processing code under the GPL license. It is always a huge honor for me to see how others build upon my work!
// Listening Wind.
// @author @deconbatch
// @version 0.1
// Processing 3.2.1
// 2019.01.05
void setup() {
size(720, 720);
colorMode(HSB, 360, 100, 100, 100);
rectMode(CENTER);
smooth();
noStroke();
noLoop();
}
void draw() {
int frameCntMax = 24 * 6;
int lineCntMax = floor(random(5.0, 8.0));
float baseWidth = width * random(0.12, 0.18) / lineCntMax;
float baseHeight = width * 0.35;
float baseHue = random(360);
float cRadianDiv = PI * 0.001;
translate(width / 2, height / 2);
for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {
background(0.0, 0.0, 90.0, 100.0);
for (int lineCnt = 0; lineCnt < lineCntMax; ++lineCnt) {
// shift start frame of easing with each line
float frameRatio = map(frameCnt, 0, frameCntMax, 0.0, 1.0);
float easingRatio = easeInOutCosine((frameRatio + lineCnt * 1.0 / lineCntMax) % 1.0);
float lineRadian = lineCnt * TWO_PI / lineCntMax;
float lineWidth = constrain(sin(lineCnt * PI / (lineCntMax - 1)), 0.0, 1.0);
for (float cRadian = 0.0; cRadian < TWO_PI; cRadian += cRadianDiv) {
float cPers = constrain((1.0 + sin(cRadian + TWO_PI * frameRatio + HALF_PI + lineRadian)) * 0.5, 0.0, 1.0);
float cSiz = (cPers + 0.1) * 1.5 * (2.0 + lineWidth);
float cHue = baseHue + sin(TWO_PI * (easingRatio + lineCnt * 1.0 / lineCntMax)) * 15.0 + 360.0;
float cSat = map(cPers, 0.0, 1.0, 80.0, 30.0);
float cBri = map(cPers, 0.0, 1.0, 60.0, 90.0);
float cAlp = map(cPers, 0.0, 1.0, 0.0, 50.0);
float cX = sin(cRadian * 3.0) * cos(cRadian) * baseWidth + (lineCnt - (lineCntMax - 1) / 2.0) * baseWidth * 4.0;
float cY = sin(cRadian + TWO_PI * easingRatio + lineRadian) * baseHeight;
fill(cHue % 360.0, cSat, cBri, cAlp);
ellipse(cX, cY, cSiz, cSiz);
ellipse(cY, cX, cSiz, cSiz);
}
}
casing(baseHue);
saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
}
exit();
}
/**
* easeInOutCubic easing function.
* @param t 0.0 - 1.0 : linear value.
* @return float 0.0 - 1.0 : eased value.
*/
private float easeInOutCosine(float t) {
return 0.5 - cos(PI * t) * 0.5;
}
/**
* casing : draw fancy casing
* @param hueBase : casing color.
*/
private void casing(float baseHue) {
fill(0.0, 0.0, 0.0, 0.0);
strokeWeight(40.0);
stroke(baseHue, 100.0, 10.0, 100.0);
rect(0.0, 0.0, width, height);
strokeWeight(30.0);
stroke(0.0, 0.0, 90.0, 100.0);
rect(0.0, 0.0, width, height);
noStroke();
}
/*
Copyright (C) 2019- 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/>
*/
Visual Variations
Experimenting with different parameters yields vastly different moods—from energetic gusts to quiet, rhythmic whispers.



