<!DOCTYPE html>
<html>
<head>
- <title>Touch Particle System</title>
+ <title>Particle Storm</title>
<style>
body { margin: 0; overflow: hidden; background: #000; touch-action: none; }
canvas { display: block; }
resizeCanvas();
const PARTICLE_COUNT = 200;
- const GRAVITY = 0.5;
- const FRICTION = 0.99;
+ const GRAVITY = 0.2;
+ const TOUCH_FRICTION = 1;
+ const NOTOUCH_FRICTION = 0.985;
const PARTICLE_RADIUS = 2.5;
- const MOUSE_RADIUS = 300;
- const COLOR_SPEED = 0.5;
+ const MOUSE_RADIUS = 400;
+ const COLOR_SPEED = 5.0;
+ const MAX_VELOCITY = 10;
+ const PARTICLE_LIMIT = 500;
let particles = [];
const touches = new Map(); // Stores active touches by identifier
update() {
if (this.dead) return;
- this.velocity.x *= FRICTION;
- this.velocity.y *= FRICTION;
+ if (touches.size == 0)
+ {
+ this.velocity.x *= NOTOUCH_FRICTION;
+ this.velocity.y *= NOTOUCH_FRICTION;
+ }
+ else
+ {
+ this.velocity.x *= TOUCH_FRICTION;
+ this.velocity.y *= TOUCH_FRICTION;
+ }
// Apply forces from all active touches
touches.forEach(touch => {
const dx = touch.x - this.x;
const dy = touch.y - this.y;
- const distance = Math.sqrt(dx * dx + dy * dy);
+ const distance = Math.max(Math.sqrt(dx * dx + dy * dy), 150);
if (distance < MOUSE_RADIUS) {
const force = GRAVITY * (MOUSE_RADIUS / distance);
this.velocity.y += (dy / distance) * force;
}
});
+
+ const velocityMag = Math.sqrt(this.velocity.x * this.velocity.x +
+ this.velocity.y * this.velocity.y);
+ const velocityScale = Math.min(MAX_VELOCITY / velocityMag, 1);
+ this.velocity.x = this.velocity.x * velocityScale;
+ this.velocity.y = this.velocity.y * velocityScale;
this.x += this.velocity.x;
this.y += this.velocity.y;
- const buffer = 100;
+ const buffer = 300;
if (this.x < -buffer ||
this.x > canvas.width + buffer ||
this.y < -buffer ||
particles = particles.filter(particle => !particle.dead);
// Add new particles for each active touch
+ if(particles.length < PARTICLE_LIMIT)
touches.forEach(touch => {
for (let i = 0; i < 5; i++) {
particles.push(new Particle(
- touch.x + Math.cos(touch.angle) * 20,
- touch.y + Math.sin(touch.angle) * 20
+ touch.x + Math.cos(touch.angle) * 80,
+ touch.y + Math.sin(touch.angle) * 80
));
}
- touch.angle += 0.1;
+ touch.angle += 0.5;
});
requestAnimationFrame(animate);
// Color rotation
setInterval(() => {
particles.forEach(p => {
- p.hue = (p.hue + COLOR_SPEED) % 360;
+ p.hue = (p.hue + COLOR_SPEED*(p.radius/4)) % 360;
p.color = `hsl(${p.hue}, 100%, 50%)`;
});
}, 50);