MarkTheArtist's picture
I want a simulation of the classic litebright game
85085e9 verified
Raw
History Blame Contribute Delete
4.83 kB
class ParticleSimulator {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.particles = [];
this.isRunning = false;
this.animationId = null;
this.init();
}
init() {
this.createParticles(25);
this.start();
// Add resize listener
window.addEventListener('resize', () => {
this.handleResize();
});
}
createParticles(count) {
this.particles = [];
const colors = [
'rgba(14, 165, 233, 0.8)',
'rgba(100, 116, 139, 0.8)',
'rgba(2, 132, 199, 0.8)',
'rgba(71, 85, 105, 0.8)'
];
for (let i = 0; i < count; i++) {
const size = Math.random() * 8 + 4;
const particle = {
x: Math.random() * this.canvas.offsetWidth,
y: Math.random() * this.canvas.offsetHeight,
size: size,
speedX: (Math.random() - 0.5) * 3,
speedY: (Math.random() - 0.5) * 3,
color: colors[Math.floor(Math.random() * colors.length)],
trail: []
};
this.particles.push(particle);
}
}
start() {
this.isRunning = true;
this.animate();
}
stop() {
this.isRunning = false;
if (this.animationId) {
cancelAnimationFrame(this.animationId);
}
}
reset() {
this.stop();
this.particles = [];
this.createParticles(25);
this.start();
}
animate() {
if (!this.isRunning) return;
// Clear canvas
this.canvas.innerHTML = '';
// Update and draw particles
this.particles.forEach(particle => {
// Update position
particle.x += particle.speedX;
particle.y += particle.speedY;
// Boundary check
if (particle.x <= 0 || particle.x >= this.canvas.offsetWidth) {
particle.speedX *= -1;
}
if (particle.y <= 0 || particle.y >= this.canvas.offsetHeight) {
particle.speedY *= -1;
}
// Add to trail
particle.trail.push({ x: particle.x, y: particle.y });
if (particle.trail.length > 10) {
particle.trail.shift();
}
// Draw trail
particle.trail.forEach((trailPos, index) => {
const trailElement = document.createElement('div');
trailElement.className = 'particle-trail';
trailElement.style.width = `${particle.size * (index / particle.trail.length)}px`;
trailElement.style.height = `${particle.size * (index / particle.trail.length)}px`;
trailElement.style.left = `${trailPos.x}px`;
trailElement.style.top = `${trailPos.y}px`;
trailElement.style.backgroundColor = particle.color.replace('0.8', `${0.3 * (index / particle.trail.length)}`);
this.canvas.appendChild(trailElement);
});
// Draw particle
const particleElement = document.createElement('div');
particleElement.className = 'particle';
particleElement.style.width = `${particle.size}px`;
particleElement.style.height = `${particle.size}px`;
particleElement.style.left = `${particle.x}px`;
particleElement.style.top = `${particle.y}px`;
particleElement.style.backgroundColor = particle.color;
particleElement.style.boxShadow = `0 0 ${particle.size * 2}px ${particle.color}`;
this.canvas.appendChild(particleElement);
});
this.animationId = requestAnimationFrame(() => this.animate());
}
handleResize() {
this.stop();
this.start();
}
updateParticleCount(count) {
this.stop();
this.createParticles(count);
this.start();
}
}
// Initialize simulator when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
const simulator = new ParticleSimulator('simulationCanvas');
// Add event listeners for control buttons
document.querySelector('button:nth-child(1)').addEventListener('click', () => {
simulator.start();
});
document.querySelector('button:nth-child(2)').addEventListener('click', () => {
simulator.stop();
});
document.querySelector('button:nth-child(3)').addEventListener('click', () => {
simulator.reset();
});
// Add event listeners for sliders
const sliders = document.querySelectorAll('input[type="range"]');
sliders[0].addEventListener('input', (e) => {
simulator.updateParticleCount(parseInt(e.target.value));
});
});