Processing Code Examples: Creative Coding Fun! Modifying Published Processing Sketches
This is an example of a modification of a published Processing code, in which the particles appear to autonomously divide into groups of different colors. The source code of the program is presented here, along with the key points of its creation.
The source code of the program is presented here, along with the key points of its production.
Original Processing Code for Modification
This example was created by modifying the code that ひさだん(@hisadan) san had published on Twitter.
//#Processing
— ひさだん (@hisadan) April 20, 2025
int i,s,n=999;
float a[]=new float[n*2],x,y,d,r,e,f;
void setup(){
size(800,800);
for(i=0;i<n;i++){
d=random(250);
r=random(TAU);
a[i]=d*sin(r);
a[i+n]=d*cos(r);}
background(0);
colorMode(HSB);}
void draw(){
fill(0,2);
square(0,0,800);
for(i=0;i<n;i++){
//cont. pic.twitter.com/uFrvtnXZ6p
Its autonomous and organic moving are attractive. So, I wanted to make some modified works.
Key Points of Reading Source Code in Creative Coding Way
At first, I refactored the minified source code for Twitter posting.
/**
* Ref. https://x.com/hisadan/status/1913976946687422638
*/
int i, s, n = 999;
float a[] = new float[n * 2];
float x, y, d, r, e, f;
void setup() {
size(800,800);
colorMode(HSB);
background(0);
// locate the particles randomly
// a[i] as x axis, a[i + n] as y axis
for (i = 0; i < n; i++) {
d = random(250);
r = random(TAU);
a[i] = d * sin(r);
a[i + n] = d * cos(r);
}
}
void draw() {
// translucent for afterimage
fill(0,2);
square(0, 0, 800);
// calculation for particle move
for(i = 0; i < n; i++) {
for(s = 0; s < n; s++) {
x = 0;
y = 0;
d = dist(a[i], a[i + n], a[s], a[s + n]);
e = (a[s] - a[i]) / d / d;
f = (a[s + n] - a[i + n]) / d / d;
if (i != s) {
if (i % 2 == s % 2) {
x += d > 100 ? -e : e;
y += d > 100 ? -f : f;
} else {
x += d > 50 ? e : -e;
y += d > 50 ? f : -f;
}
}
a[i] += x;
a[i + n] += y;
}
// color with distance from center of sketch
stroke(mag(a[i], a[i + n]), 255, 255);
point(a[i] + 400, a[i + n] + 400);
}
}
I've written some comments on source code.
This level of understanding is sufficient when reading the code for modifications, and the rest will be understood as modifications are made.
Key Points for Creative Coding Style Modifications
Since it is boring to read code all the time, I will follow the creative coding style and start modifying the code, leaving the understanding of the code there.
When making modifications, if you start with simple changes such as changing initial values, you will smoothly understand how the program works. By the time you move on to more difficult modifications such as changing movements, you will be able to see what the key parts of the code are and where the appeal is created.
Try to Change the Number of Particles
int i, s, n = 999;
Change the number of 999 to an extreme 10,000 or 10 and see the result.
Try to Change the Way to Draw
// translucent for afterimage
fill(0,2);
square(0, 0, 800);
Try opaque or transparent.
// color with distance from center of sketch
stroke(mag(a[i], a[i + n]), 255, 255);
point(a[i] + 400, a[i + n] + 400);
For example.
描画を変えてみる 🙂
— deconbatch (@deconbatch) April 22, 2025
・計算前後の座標間に線をひく
・その線の長さに応じて色を付ける
・線が短いほど太く#processing #creativecoding pic.twitter.com/D3XatxtR8t
Try to Change the Moving of Particles
d = dist(a[i], a[i + n], a[s], a[s + n]);
e = (a[s] - a[i]) / d / d;
f = (a[s + n] - a[i + n]) / d / d;
This is one of the most important points because it is the part that determines the amount of change in position. It's both a rewarding and challenging aspect of the modification.
if (i % 2 == s % 2) {
x += d > 100 ? -e : e;
y += d > 100 ? -f : f;
} else {
x += d > 50 ? e : -e;
y += d > 50 ? f : -f;
}
This is a part where I don't know what it's doing, or rather, I know what it's doing, but I don't know why it's doing this.
So, I guess it must be a key point of this work!
Example modification of this part.
Processing Code of Modified Work
Here is the Processing code of my modified work.
/**
* Processing Example Code: particles seemingly autonomously sort themselves into different color clusters.
* Ref. https://x.com/hisadan/status/1913976946687422638
*
* @author @deconbatch
* @version 0.1
* @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
* Processing 4.3.3
* 2025.05.22
*/
void setup() {
int frmMax = 24 * 10; // 24fps x 10sec
int pNumMax = 1800;
int pClass = 6;
float pIniRad = 80.0;
float pDistMax = 220.0;
float distMag = 12.0;
float baseHue = random(120.0, 300.0);
PVector curP[] = new PVector[pNumMax];
PVector prvP[] = new PVector[pNumMax];
size(720, 720);
colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
for(int pCnt = 0; pCnt < pNumMax; pCnt++){
float r = random(pIniRad);
float t = random(TAU);
curP[pCnt] = new PVector(r * cos(t), r * sin(t));
prvP[pCnt] = new PVector(curP[pCnt].x, curP[pCnt].y);
}
translate(width * 0.5, height * 0.5);
rectMode(CENTER);
blendMode(BLEND);
background(baseHue, 40.0, 10.0, 100.0);
// iterate for the number of animation frames
for (int frm = 0; frm < frmMax; frm++) {
// for afterimage
blendMode(BLEND);
fill(baseHue, 40.0, 10.0, 20.0);
noStroke();
rect(0.0, 0.0, width, height);
// calc position of points
for (int mCnt = 0; mCnt < pNumMax; mCnt++) {
for (int oCnt = 0; oCnt < pNumMax; oCnt++) {
if (mCnt != oCnt) {
float pDist = 1.0 + PVector.dist(prvP[mCnt], prvP[oCnt]);
PVector pDiv = PVector.div(PVector.mult(PVector.sub(prvP[mCnt], prvP[oCnt]), distMag), pow(pDist, 2));
if (mCnt % pClass == oCnt % pClass) {
curP[mCnt].add(pDiv.mult((pDistMax - pDist) / pDistMax));
} else {
if (pDist > pDistMax) {
curP[mCnt].sub(pDiv);
} else {
curP[mCnt].add(pDiv);
}
}
}
}
}
// calc min/max distance
float drMin = 99.0;
float drMax = -drMin;
for (int mCnt = 0; mCnt < pNumMax; mCnt++) {
float dR = PVector.dist(curP[mCnt], prvP[mCnt]) / pDistMax;
drMax = max(drMax, dR);
drMin = min(drMin, dR);
}
// draw lines
blendMode(SCREEN);
noFill();
for (int mCnt = 0; mCnt < pNumMax; mCnt++) {
float distRatio = map(PVector.dist(curP[mCnt], prvP[mCnt]) / pDistMax, drMin, drMax, 0.0, 1.0);
float hueRatio = (mCnt % pClass) * 1.0 / pClass;
float satRatio = floor(0.5 + mCnt / (pNumMax * 0.3)) / 3.0;
float briRatio = floor(0.5 + mCnt / (pNumMax * 0.2)) / 5.0;
stroke((baseHue + 90.0 + hueRatio * 120.0 + distRatio * 90.0) % 360.0,
10.0 + satRatio * (1.0 - distRatio) * 80.0,
20.0 + briRatio * 30.0 + distRatio * 30.0,
100.0
);
strokeWeight(constrain(6.0 * (1.0 - distRatio), 1.0, 6.0));
line(prvP[mCnt].x, prvP[mCnt].y, curP[mCnt].x, curP[mCnt].y);
}
// carry over
cur2prv(curP, prvP);
// make image files for animation frames
saveFrame("frames/" + String.format("%04d", frm) + ".png");
}
exit();
}
/**
* deep copy from c to p
*/
void cur2prv(PVector[] c, PVector[] p){
for(int pCnt = 0; pCnt < p.length; pCnt++){
p[pCnt].x = c[pCnt].x;
p[pCnt].y = c[pCnt].y;
}
}
Points of Modification
I decided to manage the particles with PVector.
curP[pCnt] = new PVector(r * cos(t), r * sin(t));
I separated arrays for position calculations and for the results of previous calculations, so that the results of one particle's calculations do not affect the position calculations of other particles.
PVector curP[] = new PVector[pNumMax]; // current
PVector prvP[] = new PVector[pNumMax]; // previous
I implemented a change in the particle's position calculation formula, using the condition '(mCnt % pClass == oCnt % pClass)'.
float pDist = 1.0 + PVector.dist(prvP[mCnt], prvP[oCnt]);
PVector pDiv = PVector.div(PVector.mult(PVector.sub(prvP[mCnt], prvP[oCnt]), distMag), pow(pDist, 2));
if (mCnt % pClass == oCnt % pClass) {
curP[mCnt].add(pDiv.mult((pDistMax - pDist) / pDistMax));
} else {
if (pDist > pDistMax) {
curP[mCnt].sub(pDiv);
} else {
curP[mCnt].add(pDiv);
}
}
Because of the long computation time required, I did not make real-time animation with draw() function. Instead, I've decided to use a method that writes out a still image for each frame to generate a movie.
Additional Ideas for Modification
Even with the code as it is, you can get various results by changing the initial values of the variables.
int pNumMax = 1800;
int pClass = 6;
float pIniRad = 80.0;
float pDistMax = 220.0;
float distMag = 12.0;
It would be interesting to get interesting results if these variables were not fixed values, but rather values that change as the frame progresses.
Conclusion
My modified work leaned more towards a simulation than an art piece.
It looks as if the particles by color move and gather autonomously, but in reality it is better to say that the color is changed by the group of particles that gather.
float hueRatio = (mCnt % pClass) * 1.0 / pClass;
To tell the truth, I have no idea why both the original code and the modified code work like this.
This means that even if you do not have a technical understanding of the program code, you can modify it and create a work of art with your hands. I think this is the best part of creative coding.
Without the underlying code this time, this work would not have been created.
Thank you, ひさだん(@hisadan) san for publishing this interesting example code.