In the project Generative Motion, I have experimented with 3 distinctive motions.
Wormhole experiments the circle's movement towards mouse cursor and dynamic change in size through pressing and releasing the mouse.
Cosmos focuses on how to draw arcs starting from the place where the user presses the mouse cursor and switch to another location instantly when a different coordinate is pressed on.
Chaotic Peace moves beyond the regular sine and cosine patterns by changing the amplitude of both sin and cos function with the cursor's x coordinate; I also managed to change the color of the line through time to create a rainbow-like atmosphere.
For the Generative Creatures project, my goal is to allow users to directly manipulate the creatures. I've chosen the 'Wormhole' motion as the core interactive mechanic and build upon it.
This is a minimal demo for the motion that I have expanded further.
The motions have several key features:
The creature's pupil faces the direction of the cursor, and turns to the middle if the cursor is no longer moving.
The creature follows the cursor's movement.
The creature eats the red dots and grows bigger gradually.
Click here to view the demo in detail.
I have designed a generative creature called "Magnemite". Magnemites live in "electronic land" where the magnetic fields have been distorted and standard physics rules can no longer be applied.
In the world of elctronic land, creature interaction is governed by a simple yet chaotic rule set.
Newborns are assigned a random polarity.
When a larger Magnemite nears a smaller one with an opposite pole, it absorbs the smaller creature and flips its own polarity.
If two Magnemites' poles are the same, the smaller one is forcefully repelled.
This creates a dynamic ecosystem driven by attraction, consumption, inversion, and repulsion.
For the project, the user has an immersive understanding of the virtual eco-system by acting as a "Prime Magnemite", the very first born Magnemite. User may be pushed away by larger Magnemite, or try to escape the absorption power from them.
The demo showcases two foundamental designs of this project: how the "Prime Magnemite" that user acts interacts with the user's cursor movement; and how its size grow bigger by absorbing smaller size Magnemites.
CODE:
let bodyX, bodyY;
let bodySize;
let foodSize = 50;
let food1X, food1Y;
let food2X, food2Y;
let food3X, food3Y;
let food4X, food4Y;
function setup() {
createCanvas(600, 400);
bodyX = width / 2;
bodyY = height / 2;
bodySize = 200;
food1X = random(width);
food1Y = random(height);
food2X = random(width);
food2Y = random(height);
food3X = random(width);
food3Y = random(height);
food4X = random(width);
food4Y = random(height);
}
function draw() {
background(220);
bodyX = lerp(bodyX, mouseX, 0.05);
bodyY = lerp(bodyY, mouseY, 0.05);
let angleX = mouseX - bodyX;
let angleY = mouseY - bodyY;
let distance = dist(bodyX, bodyY, mouseX, mouseY);
let pupilMaxOffset = bodySize / 8;
let pupilX = bodyX + (angleX / distance) * pupilMaxOffset;
let pupilY = bodyY + (angleY / distance) * pupilMaxOffset;
if (distance < pupilMaxOffset) {
pupilX = mouseX;
pupilY = mouseY;
}
fill(255, 100, 100);
noStroke();
circle(food1X, food1Y, foodSize);
let dist1 = dist(bodyX, bodyY, food1X, food1Y);
if (dist1 < bodySize / 2 + foodSize / 2) {
bodySize += 5;
food1X = random(width);
food1Y = random(height);
}
circle(food2X, food2Y, foodSize);
let dist2 = dist(bodyX, bodyY, food2X, food2Y);
if (dist2 < bodySize / 2 + foodSize / 2) {
bodySize += 5;
food2X = random(width);
food2Y = random(height);
}
circle(food3X, food3Y, foodSize);
let dist3 = dist(bodyX, bodyY, food3X, food3Y);
if (dist3 < bodySize / 2 + foodSize / 2) {
bodySize += 5;
food3X = random(width);
food3Y = random(height);
}
circle(food4X, food4Y, foodSize);
let dist4 = dist(bodyX, bodyY, food4X, food4Y);
if (dist4 < bodySize / 2 + foodSize / 2) {
bodySize += 5;
food4X = random(width);
food4Y = random(height);
}
// body
fill(173, 216, 230);
stroke(0);
strokeWeight(2);
circle(bodyX, bodyY, bodySize);
// eye
fill(255);
stroke(0);
strokeWeight(bodySize / 40);
circle(bodyX, bodyY, bodySize / 2);
// pupil
fill(0);
noStroke();
circle(pupilX, pupilY, bodySize / 4);
}