Today, I’m going to work on using worms to generate coral, similar to what I did way back when I was generating omnichromatic images.
In a nutshell:
- Spawn n worms
- On each tick:
- Each worm tries to randomly move one direction
- If it cannot, increment that worm’s
stuck
counter - If it can, restart the
stuck
counter - If a worm is
stuck
long enough, kill it off and spawn a new worm
Eventually, we’ll fill the entire space with colors that end up looking a bit like coral. I’ll probably extend this later, since there are a lot of cool tweaks you can do with this general idea.
let gui;
let params = {
pointCount: 10,
maxAge: 0,
maxStuck: 10,
};
let visited;
let points;
function setup() {
createCanvas(400, 400);
gui = createGuiPanel();
gui.addObject(params);
gui.setPosition(420, 0);
reset();
}
function reset() {
clear();
background(0);
visited = [];
for (var x = 0; x < width; x++) {
visited[x] = [];
for (var y = 0; y < height; y++) {
visited[x][y] = false;
}
}
points = [];
}
function draw() {
while (points.length < params.pointCount) {
points.push({
x: int(random(width)),
y: int(random(height)),
c: color(random(256), random(256), random(256)),
age: 0,
stuck: 0,
})
}
for (var i = 0; i < points.length; i++) {
var point = points[i];
point.age++;
fill(point.c);
noStroke();
rect(point.x, point.y, 1, 1);
// Try to move each point
var newX = point.x + random([-1, 0, 1]);
var newY = point.y + random([-1, 0, 1]);
if (newX == point.x && newY == point.y) {
continue;
} else if (newX < 0 || newX >= width || newY < 0 || newY >= height || visited[newX][newY]) {
point.stuck++;
} else {
point.x = newX;
point.y = newY;
visited[newX][newY] = true;
}
// Remove old points
if (params.maxAge > 0 && point.age > params.maxAge) {
points.splice(i, 1);
i--;
}
// Remove 'stuck' points
if (params.maxStuck > 0 && point.stuck > params.maxStuck) {
points.splice(i, 1);
i--;
}
}
}
Pretty cool!
I’ve also updated my p5js
Hugo shortcode with a bit of a neat trick to add the save and clear buttons:
{{ $additionalScript := `
var oldSetup = setup;
setup = () => {
oldSetup();
createButton("play/pause").mousePressed(() => {
if (isLooping()) {
noLoop();
} else {
loop();
}
});
createButton("save").mousePressed(() => {
saveCanvas('photo', 'png')
});
createButton("clear").mousePressed(() => {
if (typeof reset !== 'undefined') {
reset();
} else {
clear();
}
});
}
`}}
<iframe
width="{{ $width }}" height="{{ $height }}" frameBorder="0"
srcdoc="{{ $header }}<script>{{ .Inner }}{{ $additionalScript }}</script>{{ $footer }}"
></iframe>
So after the script that I’m embedding I will be overwriting the script provided setup
function with one that can add the buttons:
play/pause
will stop the p5js loop or start it againsave
will call the built insaveCanvas
to generate a PNG and export itclear
will call the customreset
function if defined (to do additional work, like resetting the worms in this case), the built inclear
if not
And because I’m modifying the shortcode, this will apply to all previous sketches as well. Woot.