xxxxxxxxxx
342
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Particle System</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
</head>
<body>
<script>
let numParticles = 2500;
let particles = [];
let explodingParticles = [];
let ringParticles = [];
let zoom = 600;
let isDragging = false;
let rotationX = 0;
let rotationY = 0;
let baseRotationSpeed = 0.001;
let rotationSpeedX = 0;
let rotationSpeedY = 0;
let lastMouseX;
let lastMouseY;
let currentParticleIndex = 0;
let turbulenceFactor = 0;
let turbulenceProbability = 0.1;
let colorsInverted = false;
// Add variables for custom colors
let particleColor = [255, 255, 255]; // Default particle color (white)
let bgColor = [0, 0, 0]; // Default background color (black)
// Predefined complementary color pairs
let complementaryColors = [
[[255, 255, 0], [128, 0, 128]], // Yellow and Purple
[[0, 255, 255], [255, 0, 0]], // Cyan and Red
[[255, 165, 0], [0, 0, 255]], // Orange and Blue
[[0, 255, 0], [255, 0, 255]], // Green and Magenta
[[255, 0, 255], [0, 255, 0]], // Magenta and Green
[[128, 0, 128], [255, 255, 0]], // Purple and Yellow
[[255, 0, 0], [0, 255, 255]], // Red and Cyan
[[0, 0, 255], [255, 165, 0]], // Blue and Orange
];
function setup() {
createCanvas(800, 800, WEBGL);
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle());
}
particles[currentParticleIndex].startNewJourney();
}
function draw() {
background(bgColor);
lights();
translate(0, 0, -zoom);
rotationSpeedX *= 0.9;
rotationSpeedY *= 0.9;
rotationX += rotationSpeedX;
rotationY += rotationSpeedY + baseRotationSpeed;
rotateY(rotationY);
rotateX(rotationX);
for (let p of particles) {
p.move();
p.display(particleColor);
}
for (let i = explodingParticles.length - 1; i >= 0; i--) {
let ep = explodingParticles[i];
ep.move();
ep.display(particleColor);
if (ep.size <= 0) {
explodingParticles.splice(i, 1);
}
}
for (let i = ringParticles.length - 1; i >= 0; i--) {
let rp = ringParticles[i];
rp.move();
rp.display(particleColor);
if (rp.size <= 0) {
ringParticles.splice(i, 1);
}
}
if (!particles[currentParticleIndex].isTransitioning) {
currentParticleIndex = (currentParticleIndex + 1) % numParticles;
particles[currentParticleIndex].startNewJourney();
}
}
function triggerExplosion(large) {
let phi = random(TWO_PI);
let costheta = random(-1, 1);
let u = random(1);
let theta = acos(costheta);
let r = pow(u, 1 / 3.0);
let explosionCenter = createVector(
r * sin(theta) * cos(phi),
r * sin(theta) * sin(phi),
r * cos(theta)
).mult(200);
let minVel = large ? 0.25 * 1.75 : 0.25;
let maxVel = large ? 0.75 * 1.75 : 0.75;
let numParticles = large ? 300 : 50;
for (let i = 0; i < numParticles; i++) {
explodingParticles.push(new ExplodingParticle(explosionCenter, minVel, maxVel));
}
}
function triggerRing() {
let numRingParticles = 100;
for (let i = 0; i < numRingParticles; i++) {
let angle = map(i, 0, numRingParticles, 0, TWO_PI);
let position = createVector(cos(angle) * 200, sin(angle) * 200, 0);
ringParticles.push(new RingParticle(position));
}
}
function keyPressed() {
if ((key === 'x' || key === 'X') && keyIsDown(SHIFT)) {
triggerExplosion(true);
} else if (key === 'x' || key === 'X') {
triggerExplosion(false);
} else if (key === 'o' || key === 'O') {
triggerRing();
}
if (key >= '1' && key <= '9') {
let speedMultiplier = key - '0';
baseRotationSpeed = 0.001 * pow(2, speedMultiplier - 1);
}
if (keyCode === UP_ARROW) {
turbulenceFactor += 0.1;
} else if (keyCode === DOWN_ARROW) {
turbulenceFactor -= 0.1;
if (turbulenceFactor < 0) {
turbulenceFactor = 0;
}
}
if (key === 'i' || key === 'I') {
colorsInverted = !colorsInverted;
}
if (key === 'c' || key === 'C') {
let randomIndex = int(random(complementaryColors.length));
particleColor = complementaryColors[randomIndex][0];
bgColor = complementaryColors[randomIndex][1];
}
if (key === 'b' || key === 'B') {
particleColor = [255, 255, 255];
bgColor = [0, 0, 0];
}
}
function mouseWheel(event) {
zoom -= event.delta * 0.05;
zoom = constrain(zoom, 200, 2000);
}
function mousePressed() {
if (mouseButton === LEFT) {
isDragging = true;
lastMouseX = mouseX;
lastMouseY = mouseY;
}
}
function mouseReleased() {
if (mouseButton === LEFT) {
isDragging = false;
}
}
function mouseDragged() {
if (isDragging) {
let dx = mouseX - lastMouseX;
let dy = mouseY - lastMouseY;
rotationSpeedY = dx * 0.01;
rotationSpeedX = -dy * 0.01;
lastMouseX = mouseX;
lastMouseY = mouseY;
}
}
class Particle {
constructor() {
let phi = random(TWO_PI);
let costheta = random(-1, 1);
let u = random(1);
let theta = acos(costheta);
let r = pow(u, 1 / 3.0);
this.position = createVector(
r * sin(theta) * cos(phi),
r * sin(theta) * sin(phi),
r * cos(theta)
).mult(200);
this.originalPosition = this.position.copy();
this.velocity = p5.Vector.random3D().mult(0.036);
this.size = random(0.7, 1.47);
this.speed = 0.036;
this.isTransitioning = false;
this.transitionProgress = 0;
this.transitionDuration = random(240, 480);
}
move() {
if (this.isTransitioning) {
this.transitionProgress++;
let t = this.transitionProgress / this.transitionDuration;
t = t * t * (3 - 2 * t) * (3 - 2 * t);
this.position.lerp(this.targetPosition, t);
if (this.position.mag() > 200) {
this.position.normalize().mult(200);
}
if (this.transitionProgress >= this.transitionDuration) {
this.isTransitioning = false;
}
} else {
this.position = this.originalPosition.copy();
if (turbulenceFactor > 0 && random(1) < turbulenceProbability) {
let noiseScale = 0.1;
let noiseOffset = createVector(
this.turbulence(this.position.x, this.position.y, this.position.z, noiseScale),
this.turbulence(this.position.y, this.position.z, this.position.x, noiseScale),
this.turbulence(this.position.z, this.position.x, this.position.y, noiseScale)
).mult(turbulenceFactor);
this.position.add(noiseOffset);
}
this.position.add(this.velocity);
if (this.position.mag() > 200) {
this.position.normalize().mult(200);
this.velocity = p5.Vector.random3D().mult(0.036);
}
}
}
display(particleColor) {
stroke(particleColor);
strokeWeight(this.size);
point(this.position.x, this.position.y, this.position.z);
}
startNewJourney() {
let phi = random(TWO_PI);
let costheta = random(-1, 1);
let u = random(1);
let theta = acos(costheta);
let r = pow(u, 1 / 3.0);
this.targetPosition = createVector(
r * sin(theta) * cos(phi),
r * sin(theta) * sin(phi),
r * cos(theta)
).mult(200);
this.targetPosition.add(p5.Vector.random3D().mult(50));
if (this.targetPosition.mag() > 200) {
this.targetPosition.normalize().mult(200);
}
this.isTransitioning = true;
this.transitionProgress = 0;
this.transitionDuration = random(240, 480);
}
turbulence(x, y, z, scale) {
let value = 0.0;
let size = scale;
while (size >= 1) {
value += noise(x / size, y / size, z / size) * size;
size /= 2.0;
}
return value;
}
}
class ExplodingParticle {
constructor(center, minVel, maxVel) {
this.position = center.copy();
this.velocity = p5.Vector.random3D().mult(random(minVel, maxVel));
this.size = random(0.7, 1.47);
this.lifeSpan = 180;
this.shrinkRate = this.size / this.lifeSpan;
}
move() {
this.position.add(this.velocity);
this.size -= this.shrinkRate;
if (this.size < 0) this.size = 0;
}
display(particleColor) {
stroke(particleColor, map(this.size, 0, 1.47, 0, 255));
strokeWeight(this.size);
point(this.position.x, this.position.y, this.position.z);
}
}
class RingParticle {
constructor(pos) {
this.position = pos.copy();
this.velocity = createVector(pos.x, pos.y, 0).normalize().mult(2);
this.size = random(1, 2);
this.lifeSpan = 180;
this.shrinkRate = this.size / this.lifeSpan;
}
move() {
this.position.add(this.velocity);
this.size -= this.shrinkRate;
if (this.size < 0) this.size = 0;
}
display(particleColor) {
stroke(particleColor, map(this.size, 0, 2, 0, 255));
strokeWeight(this.size);
point(this.position.x, this.position.y, this.position.z);
}
}
</script>
</body>
</html>
ccccc