html--烟花

时间:2024-04-10 21:50:14
// Code by Matheus Lin // While developing a version of "Chain Reaction", I ended up on // those "fireworks-like" things. I leave it to you here. // Chain Reaction coming up next! // Configs var screenWidth = window.innerWidth; var screenHeight = window.innerHeight; var minVx = -10; var deltaVx = 20; var minVy = 25 var deltaVy = 15; var minParticleV = 5; var deltaParticleV = 5; var gravity = 1; var explosionRadius = 200; var bombRadius = 10; var explodingDuration = 100; var explosionDividerFactor = 10; // I couldn't find a better name. Got any? var nBombs = 1; // initial var percentChanceNewBomb = 5; // Color utils forked from http://andreasstorm.com/ // (or someone who forked from there) function Color(min) { min = min || 0; this.r = colorValue(min); this.g = colorValue(min); this.b = colorValue(min); this.style = createColorStyle(this.r, this.g, this.b); }; function colorValue(min) { return Math.floor(Math.random() * 255 + min); } function createColorStyle(r,g,b) { return 'rgba(' + r + ',' + g + ',' + b + ', 0.8)'; } // A Bomb. Or firework. function Bomb(){ var self = this; self.radius = bombRadius; self.previousRadius = bombRadius; self.explodingDuration = explodingDuration; self.hasExploded = false; self.alive = true; self.color = new Color(); self.px = (window.innerWidth / 4) + (Math.random() * window.innerWidth / 2); self.py = window.innerHeight; self.vx = minVx + Math.random() * deltaVx; self.vy = (minVy + Math.random() * deltaVy) * -1; // because y grows downwards self.duration = self.update = function(particlesVector){ if(self.hasExploded){ var deltaRadius = explosionRadius - self.radius; self.previousRadius = self.radius; self.radius += deltaRadius / explosionDividerFactor; self.explodingDuration--; if(self.explodingDuration == 0){ self.alive = false; } } else{ self.vx += 0; self.vy += gravity; if(self.vy >= 0){ // invertion point self.explode(particlesVector); } self.px += self.vx; self.py += self.vy; } }; self.draw = function(ctx){ ctx.beginPath(); ctx.arc(self.px, self.py, self.previousRadius, 0, Math.PI * 2, false); if(self.hasExploded){ } else{ ctx.fillStyle = self.color.style; ctx.lineWidth = 1; ctx.fill(); } }; self.explode = function(particlesVector){ self.hasExploded = true; var e = 3 + Math.floor(Math.random() * 3); for(var j = 0; j < e; j++){ var n = 10 + Math.floor(Math.random() * 21); // 10 - 30 var speed = minParticleV + Math.random() * deltaParticleV; var deltaAngle = 2 * Math.PI / n; var initialAngle = Math.random() * deltaAngle; for(var i = 0; i < n; i++){ particlesVector.push(new Particle(self, i * deltaAngle + initialAngle, speed)); } } }; } function Particle(parent, angle, speed){ var self = this; self.px = parent.px; self.py = parent.py; self.vx = Math.cos(angle) * speed; self.vy = Math.sin(angle) * speed; self.color = parent.color; self.duration = 40 + Math.floor(Math.random()*20); self.alive = true; self.update = function(){ self.vx += 0; self.vy += gravity / 10; self.px += self.vx; self.py += self.vy; self.radius = 3; self.duration--; if(self.duration <= 0){ self.alive = false; } }; self.draw = function(ctx){ ctx.beginPath(); ctx.arc(self.px, self.py, self.radius, 0, Math.PI * 2, false); ctx.fillStyle = self.color.style; ctx.lineWidth = 1; ctx.fill(); }; } function Controller(){ var self = this; self.canvas = document.getElementById("screen"); self.canvas.width = screenWidth; self.canvas.height = screenHeight; self.ctx = self.canvas.getContext('2d'); function setSpeedParams(){ var heightReached = 0; var vy = 0; while(heightReached < screenHeight && vy >= 0){ vy += gravity; heightReached += vy; } minVy = vy / 2; deltaVy = vy - minVy; vx = (1 / 4) * screenWidth / (vy / 2); minVx = -vx; deltaVx = 2*vx; }; self.resize = function(){ screenWidth = window.innerWidth; screenHeight = window.innerHeight; self.canvas.width = screenWidth; self.canvas.height = screenHeight; setSpeedParams(); }; self.resize(); window.onresize = self.resize; self.init = function(){ self.readyBombs = []; self.explodedBombs = []; self.particles = []; for(var i = 0; i < nBombs; i++){ self.readyBombs.push(new Bomb()); } } self.update = function(){ var aliveBombs = []; while(self.explodedBombs.length > 0){ var bomb = self.explodedBombs.shift(); bomb.update(); if(bomb.alive){ aliveBombs.push(bomb); } } self.explodedBombs = aliveBombs; var notExplodedBombs = []; while(self.readyBombs.length > 0){ var bomb = self.readyBombs.shift(); bomb.update(self.particles); if(bomb.hasExploded){ self.explodedBombs.push(bomb); } else{ notExplodedBombs.push(bomb); } } self.readyBombs = notExplodedBombs; var aliveParticles = []; while(self.particles.length > 0){ var particle = self.particles.shift(); particle.update(); if(particle.alive){ aliveParticles.push(particle); } } self.particles = aliveParticles; } self.draw = function(){ self.ctx.beginPath(); self.ctx.fillStyle='rgba(0, 0, 0, 0.1)'; // Ghostly effect self.ctx.fillRect(0, 0, self.canvas.width, self.canvas.height); for(var i = 0; i < self.readyBombs.length; i++){ self.readyBombs[i].draw(self.ctx); } for(var i = 0; i < self.explodedBombs.length; i++){ self.explodedBombs[i].draw(self.ctx); } for(var i = 0; i < self.particles.length; i++){ self.particles[i].draw(self.ctx); } } self.animation = function(){ self.update(); self.draw(); if(Math.random() * 100 < percentChanceNewBomb) { self.readyBombs.push(new Bomb()); } requestAnimationFrame(self.animation); } } var controller = new Controller(); controller.init(); requestAnimationFrame(controller.animation);