xxxxxxxxxx
209
// Define arrays to store mover and attractor objects
let movers = [];
let attractors = [];
// Define constants for simulation parameters
const numMovers = 200; // Number of mover objects
const numAttractors = 5; // Number of attractor objects
const repelDistance = 10; // Distance at which repulsion begins
const repelStrength = 20000; // Increased repulsion strength
const attractionDistance = 1000; // Distance at which attraction begins
const attractionStrength = 2000; // Attraction strength between attractors
const moverRepelDistance = 10; // Distance at which movers repel each other
const moverRepelStrength = 10000; // Repulsion strength between movers
let attractToMouse = false; // Flag to determine if attractors should be attracted to the mouse
function setup() {
createCanvas(400, 400);
// Create movers with random initial positions
for (let i = 0; i < numMovers; i++) {
movers.push(new Mover(random(width), random(height)));
}
// Create attractors with random initial positions
for (let i = 0; i < numAttractors; i++) {
attractors.push(createVector(random(width), random(height)));
}
}
function draw() {
background(220);
// Move attractors randomly
moveAttractorsRandomly();
// Apply forces to movers based on attraction and repulsion
applyForcesToMovers();
// Apply attraction between attractors
applyAttractionBetweenAttractors();
// Draw attractors as red points
for (let attractor of attractors) {
fill(220);
noStroke();
ellipse(attractor.x, attractor.y, 5, 5);
}
}
function moveAttractorsRandomly() {
for (let attractor of attractors) {
// Add a random 2D vector to simulate random movement
attractor.add(p5.Vector.random2D().mult(2));
// Constrain attractor positions within canvas bounds
attractor.x = constrain(attractor.x, 0, width);
attractor.y = constrain(attractor.y, 0, height);
}
}
function applyForcesToMovers() {
for (let i = 0; i < movers.length; i++) {
let mover = movers[i];
// Apply repulsion from attractors, mouse, other movers, and attraction to mouse
applyRepulsionFromAttractors(mover);
applyRepulsionFromMouse(mover);
applyRepulsionBetweenMovers(mover);
applyAttractionToMouse(mover);
applyTurbulence(mover);
// Update mover position, velocity, and display
mover.update();
mover.display();
// Check if mover went out of canvas bounds and wrap around
mover.checkEdges();
}
}
function applyRepulsionFromAttractors(mover) {
for (let attractor of attractors) {
let force = attractor.copy().sub(mover.pos);
let distance = force.mag();
if (distance < repelDistance) {
// Calculate repulsion strength and apply it
let strength = -repelStrength / (distance * distance);
force.setMag(strength);
mover.applyForce(force);
} else if (distance < attractionDistance) {
// Calculate attraction strength and apply it
let strength = 5000 / (distance * distance);
force.setMag(strength);
mover.applyForce(force);
}
}
}
function applyRepulsionFromMouse(mover) {
if (attractToMouse && mouseIsPressed) {
// Calculate repulsion force from mouse and apply it
let mouseForce = createVector(mouseX, mouseY).sub(mover.pos);
let mouseDistance = mouseForce.mag();
if (mouseDistance < repelDistance) {
let mouseStrength = -repelStrength / (mouseDistance * mouseDistance);
mouseForce.setMag(mouseStrength);
mover.applyForce(mouseForce);
}
}
}
function applyRepulsionBetweenMovers(mover) {
for (let j = 0; j < movers.length; j++) {
if (mover !== movers[j]) {
let otherMover = movers[j];
let force = otherMover.pos.copy().sub(mover.pos);
let distance = force.mag();
if (distance < moverRepelDistance) {
// Calculate repulsion strength and apply it
let strength = -moverRepelStrength / (distance * distance);
force.setMag(strength);
mover.applyForce(force);
}
}
}
}
function applyAttractionToMouse(mover) {
if (attractToMouse && mouseIsPressed) {
// Calculate attraction force from mouse and apply it
let mouseAttraction = createVector(mouseX, mouseY).sub(mover.pos);
let mouseAttractionDistance = mouseAttraction.mag();
let mouseAttractionStrength =
500 / (mouseAttractionDistance * mouseAttractionDistance);
mouseAttraction.setMag(mouseAttractionStrength);
mover.applyForce(mouseAttraction);
}
}
function applyTurbulence(mover) {
// Generate random turbulence force and apply it
let turbulence = createVector(random(-1, 1), random(-1, 1));
turbulence.mult(0.1);
mover.applyForce(turbulence);
}
function applyAttractionBetweenAttractors() {
for (let i = 0; i < attractors.length; i++) {
for (let j = i + 1; j < attractors.length; j++) {
let force = attractors[j].copy().sub(attractors[i]);
let distance = force.mag();
if (distance < attractionDistance) {
// Calculate attraction strength and apply it between attractors
let strength = attractionStrength / (distance * distance);
force.setMag(strength);
attractors[i].add(force);
attractors[j].sub(force);
}
}
}
}
// Define a Mover class for objects that move in the simulation
class Mover {
constructor(x, y) {
this.pos = createVector(x, y);
this.vel = createVector();
this.acc = createVector();
this.maxSpeed = 5;
}
applyForce(force) {
// Apply a force to the mover
this.acc.add(force);
}
update() {
// Update position, velocity, and reset acceleration
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.set(0, 0);
}
display() {
// Display the mover as a small ellipse
fill(0);
noStroke();
ellipse(this.pos.x, this.pos.y, 5, 5);
}
checkEdges() {
// Check if the mover went out of canvas bounds and wrap around
if (this.pos.x > width) this.pos.x = 0;
else if (this.pos.x < 0) this.pos.x = width;
if (this.pos.y > height) this.pos.y = 0;
else if (this.pos.y < 0) this.pos.y = height;
}
}
function mouseClicked() {
// Toggle the attractToMouse flag on mouse click, affecting mouse interaction
attractToMouse = !attractToMouse;
}