Generative Sea Creatures: A Deep Dive into Creative Coding
Hello! 👋 Credit to x.com/yuruyurau for the tweet & code. We’ve been inspired by the tweet below and decided to create a sandbox for you to quickly generate your own sea creatures 🐡
a=(x,y,d=mag(k=x/8-25,e=y/8-25)**2/99)=>[(q=x/3+k*.5/cos(y*5)*sin(d*d-t))*sin(c=d/2-t/8)+e*sin(d+k-t)+200,(q+y/8+d*9)*cos(c)+200]
— ア (@yuruyurau) November 11, 2024
t=0,draw=$=>{t||createCanvas(w=400,w);background(6).stroke(255,96);for(t+=PI/60,y=99;y<300;y+=5)for(x=99;++x<300;)point(...a(x,y))}#つぶやきProcessing pic.twitter.com/4dBdKEe1Zu
Reverse Engineering the Code⌗
Here’s the original code snippet from the tweet:
a=(x,y,d=mag(k=x/8-25,e=y/8-25)**2/99)=>[(q=x/3+k*.5/cos(y*5)*sin(d*d-t))*sin(c=d/2-t/8)+e*sin(d+k-t)+200,(q+y/8+d*9)*cos(c)+200]
t=0,draw=$=>{t||createCanvas(w=400,w);background(6).stroke(255,96);for(t+=PI/60,y=99;y<300;y+=5)for(x=99;++x<300;)point(...a(x,y))}
After un-minifying, formatting and adding some comments, we get:
let t = 0; // Initialize the time variable
function setup() {
// Set up the canvas with the full width and height of the window
createCanvas(windowWidth, windowHeight);
// Set the background color to a medium gray
background(100);
}
// Define a function to calculate and return coordinates
// Takes in x, y, and an optional parameter d, which is calculated as the square of the distance from (x/8-25, y/8-25)
function a(x, y, d = mag(k = x / 8 - 25, e = y / 8 - 25) ** 2 / 99) {
// q represents a calculated variable dependent on x and k
const q = (x / 3 + k * 0.5 / cos(y * 5) * sin(d * d - t));
// c is derived based on d and the global variable t
const c = d / 2 - t / 8;
// Return an array of two values for point placement:
// - The first element is a calculation based on q and sine functions
// - The second element is a calculation based on q, y, d, and cosine
return [
q * sin(c) + e * sin(d + k - t) + 200, // x-coordinate
(q + y / 8 + d * 9) * cos(c) + 200 // y-coordinate
];
}
// Override the draw function with a custom function to create the animation
draw = function() {
// Initialize the canvas if t is 0 (first run)
if (t === 0) {
createCanvas(w = 400, w); // Square canvas with width and height of 400
}
background(6); // Dark background
stroke(255, 96); // Set the stroke color to light gray with a slight alpha for the effect
// Increment the time variable by a small angle (PI/60 radians)
t += PI / 60;
// Loop through y-coordinates from 99 to 300 in increments of 5
for (let y = 99; y < 300; y += 5) {
// Loop through x-coordinates from 100 to 299
for (let x = 99; ++x < 300;) {
// Draw a point at the coordinates returned by the function `a(x, y)`
point(...a(x, y));
}
}
};
😅 Ok - that’s a little more readable. Try pasting this code into a P5.js editor: editor.p5js.org
💥 Boom! That is really cool 🤓
But, how can we add some interactivity for the user? 🤔
Slide into Action⌗
In order to control how the sea creatures look and move, we can add sliders to adjust some of the values.
let t = 0;
let speedSlider;
function setup() {
... // Same setup code as before
// Create a slider for controlling the speed
speedSlider = createSlider(20, 70, 60);
speedSlider.position(0,20);
speedSlider.size(200, 20);
}
draw = function() {
... // Same draw code as before
// Update the time increment based on the slider value
t += PI / speedSlider.value();
};
Now you can control the speed of the animation by moving the slider! 🐢
After adding a few more sliders for different values, you can create a more interactive experience for generating sea creatures.
Naming the Beastie⌗
The original tweet and code reminded us of a deep sea exploration, where you might encounter strange and wonderful creatures in the depths of the ocean. Every new discovery deserves a name, right? 😄
We’ll add a text element to display the name of the current sea creature. This text will change based on the values of the sliders (see the full code to see where the other slider values are used).
// Converts an integer to a code name (e.g., 1 -> A, 2 -> B, 27 -> AA, etc.)
function intToCode(n) {
let name = '';
while (n > 0) {
let remainder = (n - 1) % 26;
name = String.fromCharCode(65 + remainder) + name;
n = Math.floor((n - 1) / 26);
}
return name;
}
// Generate a name for the sea creature based on the slider values
function getCreatureName(){
return sizeSlider.value() + '' + intToCode(sizeSlider.value()*50) + '/' + complexitySlider.value() + '-' + intToCode(speedSlider.value()) + shapeSlider.value() + ':' + focusSlider.value();
}
💡 3ET/5-BH99:1 is born! 🍼
Conclusion: Dive Deeper! 🤿⌗
Here’s the final full code for generating your own sea creatures. Try remixing it by adding more sliders, changing the calculations, or creating new visual effects. The ocean of creative coding is vast and full of possibilities! 🌊
Thanks again to x.com/yuruyurau for the inspiration! 🙌