JINBO Is Not a BOids. How to make a Boids imitation.
It's an experimental trial to make animation like Boids using the Vector Field method.
What's Boids?
Boids is an artificial life simulation program by Craig Reynolds.
These moving looks like a flock of birds. So it named "Bird-oid".
https://en.wikipedia.org/wiki/Boids
Boids need Separation, Alignment, and Cohesion. And my implementation in this article ignores them.
So it's not Boids at all, it just these motion looks like a Boids.
Real pleasure of Creative coding.
I love Vector Field. It has infinite possibilities.
Drawing vector field | GenerateMe
https://generateme.wordpress.com/2016/04/24/drawing-vector-field/
ベクター・フィールド静止画のコードを元にアニメーションhttps://t.co/Hj1bRh78wN#processing #creativecoding #generative pic.twitter.com/6AuNKDlkjn— deconbatch (@deconbatch) October 3, 2019
When I was playing with my Vector Field example, I had an idea to draw a part of Vector Field flow.
And I made an animation with that idea, I thought it looks like a Boids.
線のお尻を消していけば流れに沿って動いていくように見えて、こりゃインチキ・ボイドが作れるかも? #processing #creativecoding #generative pic.twitter.com/pKXKG8x3hk— deconbatch (@deconbatch) October 3, 2019
But as you know, if you calculate Vector Field with points coordinates only, you get the same flow line.
noise(x, y);
— deconbatch (@deconbatch) October 19, 2019
So, I put particle number as the third dimension on noise(). It makes different vector fields each particle.
noise(n, x, y);
ノイズの 3D 目に各パーティクルの順番を入れてバラバラの動きにできる。👍— deconbatch (@deconbatch) October 19, 2019
でも、3D 目の差が大きすぎるとバラバラさがバラバラ過ぎることに。😩#processing #creativecoding pic.twitter.com/ckG8xDlvvY
And then, tune the third dimension of noise(), it becomes fake Boids!
noise(n * 0.01, x, y);
— deconbatch (@deconbatch) October 19, 2019
The 'Processing' code example (Java).
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.
/**
* So Many Ways.
* draw vector field flowing images that imitate the Boids.
*
* @author @deconbatch
* @version 0.1
* Processing 3.2.1
* 2019.10.19
*/
import java.util.List;
void setup() {
size(720, 446);
colorMode(HSB, 360, 100, 100, 100);
smooth();
noStroke();
noLoop();
}
void draw() {
int imgMax = 3; // 3 vector field flowing images
int frmMax = 24 * 6; // 24fps x 6s movie
int plotMax = 2000;
float plotDiv = 0.001;
float baseHue = random(360.0);
for (int imgCnt = 0; imgCnt < imgMax; ++imgCnt) {
float initDiv = 0.1;
float plotMult = random(2.0, 5.0);
float baseBri = 3.0;
float baseSiz = random(3.0, 6.0);
baseHue += 120.0; // 120 hue difference each cycle
noiseSeed(floor(baseHue * plotMult)); // make diffrent flow each cycle
List<List<PVector>> vectorField = getVectorfield(initDiv, plotMax, plotDiv, plotMult);
for (int frmCnt = 0; frmCnt < frmMax; ++frmCnt) {
float frmRatio = map(frmCnt, 0, frmMax, 0.0, 1.0);
float easeRatio = easeInOutCubic(frmRatio);
float piFrm = sin(PI * frmRatio);
int plotLen = floor(plotMax * 0.05 * piFrm) + 5;
int plotStart = floor((plotMax - plotLen) * easeRatio);
blendMode(DIFFERENCE);
background(baseHue % 360.0, 10.0 * piFrm, 90.0, 100);
// draw vector field
int flowCnt = 0;
for (List<PVector> flows : vectorField) {
flowCnt++;
for (int plotCnt = plotStart; plotCnt < plotStart + plotLen; plotCnt++) {
PVector points = flows.get(plotCnt);
float plotRatio = map(plotCnt, plotStart, plotStart + plotLen, 0.0, 1.0);
float eHue = baseHue + plotRatio * 60.0 + (flowCnt % 4) * 10.0;
float eSat = map(sin(PI * plotRatio), 0.0, 1.0, 80.0, 40.0);
float eBri = baseBri * sin(HALF_PI * plotRatio);
float eSiz = baseSiz * (1.0 + noise(flowCnt) * 3.0) * sin(HALF_PI * plotRatio);
fill(eHue % 360.0, eSat, eBri, 100.0);
ellipse(points.x * width, points.y * height, eSiz, eSiz);
}
}
blendMode(BLEND);
casing();
saveFrame("frames/" + String.format("%01d", imgCnt) + String.format("%03d", frmCnt) + ".png");
}
}
exit();
}
/**
* getVectorfield calculate whole Vector Field flow and return them with List.
* @param _initDiv : the distance of each flow start point.
* @param _plotMax : how many time calculate Vector Field each flow.
* @param _plotDiv : distance of step.
* @param _plotMult : not zero. curvature.
* @return List<List<PVector>> : each flow List(each points List(coordinates))
*/
private List<List<PVector>> getVectorfield(float _initDiv, int _plotMax, float _plotDiv, float _plotMult) {
float noiseDiv = 1.8 / _plotMult;
int flowCnt = 0;
List<List<PVector>> vectorField = new ArrayList();
for (float xInit = -1.0; xInit <= 2.0; xInit += _initDiv) {
for (float yInit = -1.0; yInit <= 2.0; yInit += _initDiv) {
List<PVector> flows = new ArrayList();
flowCnt++;
float xCurr = xInit;
float yCurr = yInit;
for (int plotCnt = 0; plotCnt < _plotMax; ++plotCnt) {
float xPrev = xCurr;
float yPrev = yCurr;
float rCurr = TWO_PI * noise(flowCnt * 0.002, xPrev * noiseDiv, yPrev * noiseDiv);
xCurr += _plotDiv * cos(rCurr * _plotMult);
yCurr += _plotDiv * sin(rCurr * _plotMult);
flows.add(new PVector(xCurr, yCurr));
}
vectorField.add(flows);
}
}
return vectorField;
}
/**
* 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;
}
/**
* casing : draw fancy casing
*/
private void casing() {
fill(0.0, 0.0, 0.0, 0.0);
strokeWeight(46.0);
stroke(0.0, 0.0, 30.0, 100.0);
rect(0.0, 0.0, width, height);
strokeWeight(42.0);
stroke(0.0, 0.0, 100.0, 100.0);
rect(0.0, 0.0, width, height);
noStroke();
noFill();
}
/*
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/>
*/
Yet another example images.
They seems to love my fault work most.🤣
— deconbatch (@deconbatch) October 5, 2019