xxxxxxxxxx
210
let shapes = [];
let rippleForceRadius = 100;
class Shape {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
this.maxForce = 0.05;
this.maxSpeed = 5;
this.rotation = random(TWO_PI);
this.typeVariation = floor(random(3)); // 0: none, 1: filled, 2: smaller inner shape
}
applyForce(force) {
this.acceleration.add(force);
}
repelForce(other) {
let force = p5.Vector.sub(this.position, other.position);
let distance = force.mag();
force.normalize();
force.div(distance * distance);
return force;
}
edges() {
if (this.position.y > height) {
this.position.y = 0;
}
if (this.position.y < 0) {
this.position.y = height;
}
}
update() {
this.position.add(this.velocity);
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed);
this.acceleration.mult(0);
}
display() {
// This method will be overridden by each subclass
}
attractToRipple(ripplePosition) {
let force = p5.Vector.sub(ripplePosition, this.position);
let distance = force.mag();
if (distance < rippleForceRadius) {
force.normalize();
force.mult(-this.maxForce * 3);
this.applyForce(force);
}
}
}
class Star extends Shape {
display() {
push();
translate(this.position.x, this.position.y);
rotate(this.rotation);
stroke(255); // White color
if (this.typeVariation === 1) {
fill(255);
} else {
noFill();
}
beginShape();
for (let i = 0; i < 5; i++) {
let x = cos(i * TWO_PI / 5) * 10;
let y = sin(i * TWO_PI / 5) * 10;
vertex(x, y);
}
endShape(CLOSE);
if (this.typeVariation === 2) {
// Draw a smaller star inside
beginShape();
for (let i = 0; i < 5; i++) {
let x = cos(i * TWO_PI / 5) * 5;
let y = sin(i * TWO_PI / 5) * 5;
vertex(x, y);
}
endShape(CLOSE);
}
pop();
}
}
class Circle extends Shape {
display() {
push();
translate(this.position.x, this.position.y);
rotate(this.rotation);
stroke(255); // White color
if (this.typeVariation === 1) {
fill(255);
} else {
noFill();
}
ellipse(0, 0, 20, 20);
if (this.typeVariation === 2) {
// Draw a smaller circle inside
ellipse(0, 0, 10, 10);
}
pop();
}
}
class Square extends Shape {
display() {
push();
translate(this.position.x, this.position.y);
rotate(this.rotation);
stroke(255); // White color
if (this.typeVariation === 1) {
fill(255);
} else {
noFill();
}
rectMode(CENTER);
rect(0, 0, 20, 20);
if (this.typeVariation === 2) {
// Draw a smaller square inside
rect(0, 0, 10, 10);
}
pop();
}
}
class Triangle extends Shape {
display() {
push();
translate(this.position.x, this.position.y);
rotate(this.rotation);
stroke(255); // White color
if (this.typeVariation === 1) {
fill(255);
} else {
noFill();
}
beginShape();
vertex(0, -10);
vertex(10, 10);
vertex(-10, 10);
endShape(CLOSE);
if (this.typeVariation === 2) {
// Draw a smaller triangle inside
beginShape();
vertex(0, -5);
vertex(5, 5);
vertex(-5, 5);
endShape(CLOSE);
}
pop();
}
}
function setup() {
createCanvas(400, 400);
for (let i = 0; i < width; i += 40) {
let y = random([0, height]); // Randomly choose top or bottom
let randShape = floor(random(4));
switch (randShape) {
case 0:
shapes.push(new Star(i, y));
break;
case 1:
shapes.push(new Circle(i, y));
break;
case 2:
shapes.push(new Square(i, y));
break;
case 3:
shapes.push(new Triangle(i, y));
break;
}
}
}
function draw() {
background(0); // Black background
for (let shape of shapes) {
shape.edges();
for (let other of shapes) {
let d = dist(shape.position.x, shape.position.y, other.position.x, other.position.y);
if (d < 30) { // Repulsion only when shapes are closer
let force = shape.repelForce(other);
shape.applyForce(force);
}
}
shape.update();
shape.display();
}
}
function mousePressed() {
let ripplePosition = createVector(mouseX, mouseY);
for (let shape of shapes) {
shape.attractToRipple(ripplePosition);
}
}
function keyPressed() {
if (key === ' ') {
save("test.svg");
}
}