const WIDTH = 800; const HEIGHT = 800; const NCRITTERS = 10; const CLOSE = 20; const BOUNCE = 0.02; const STUN = 10; const MIN_RADIUS = 2; const HIDE_SPEED = 10.5; const pointer = { x: 0, y: 0 }; const critters = []; let lights = "off"; function dist(c1, c2) { const dx = c1.x - c2.x; const dy = c1.y - c2.y; return Math.sqrt(dx * dx + dy * dy); } class Critter { constructor(i) { this.i = i; this.x = Math.random() * WIDTH; this.y = Math.random() * HEIGHT; this.vx = Math.random() * 0.1 - 0.05; this.vy = Math.random() * 0.1 - 0.05; this.status = "go"; } init() { const i0 = `c00${this.i}`; this.elt = document.getElementById(i0); console.log(`elt ${i0} ${this.elt}`); } go_v(pos, vel) { if( pos < 10 ) { return vel + 0.01; } else if ( pos > WIDTH - 10 ) { return vel - 0.01; } else { return vel + Math.random() * 0.01 - 0.005; } } update() { if( this.status === "hide" ) { if( this.tick > STUN ) { this.tick--; this.elt.setAttribute("r", this.tick + MIN_RADIUS); } else { this.hide_vec = Math.atan2(this.y - pointer.y, this.x - pointer.x); this.vx = Math.cos(this.hide_vec) * HIDE_SPEED; this.vy = Math.sin(this.hide_vec) * HIDE_SPEED; } } if( this.status === "collide" ) { this.tick--; if( this.tick === 0 ) { this.status = "go"; this.elt.setAttribute("fill", "blue"); } } if( this.status === "go" ) { const collisions = critters.filter((c) => c.i != this.i && dist(c, this) < CLOSE); if( collisions.length > 0 ) { const hit = collisions[0]; this.status = "collide"; this.tick = 20; this.elt.setAttribute("fill", "red"); this.vx = (this.x - collisions[0].x) * BOUNCE; this.vy = (this.y - collisions[0].y) * BOUNCE; hit.status = "collide"; hit.tick = 20; hit.vx = -this.vx; hit.vy = -this.vy; } else { this.vx = this.go_v(this.x, this.vx); this.vy = this.go_v(this.y, this.vy); } } this.x += this.vx; this.y += this.vy; this.elt.setAttribute("cx", this.x); this.elt.setAttribute("cy", this.y); } } document.addEventListener('DOMContentLoaded', () => { const svg = document.getElementsByTagName("svg")[0]; if (svg) { // Check if container exists for( let i = 0; i < NCRITTERS; i++ ) { const c = new Critter(i); c.init(i); c.update(); critters.push(c); } svg.addEventListener("click", () => { const dark = document.getElementById("dark"); if( lights === "on" ) { lights = "off"; dark.setAttribute("fill-opacity", "0.8"); for( const c of critters ) { c.status = "go"; } } else { lights = "on"; dark.setAttribute("fill-opacity", "0"); for( const c of critters ) { c.status = "hide"; c.tick = Math.random() * 10 + 15; } } }); } else { } }); function animate() { requestAnimationFrame(animate); /* const rect = svg.getBoundingClientRect(); const x = pointer.x - rect.left; const y = pointer.y - rect.top; */ for( const c of critters ) { c.update(); } } animate();