// Targeted Lightning, a lightning which will try to go to the specified target position, but has a random factor to define where it actually jumps to. //Made by Boomer Shin /* Color functions, forked from some animation which was forked from http://andreasstorm.com/ once, long ago. Those are very handy for random colors, you know? */ 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)'; }; /* Other utility functions */ function distance2dPositions(dx, dy){ return Math.sqrt(dx*dx + dy*dy); }; function distance2dCoordinates(x1, x2, y1, y2){ var dx = x2 - x1; var dy = y2 - y1; var dist = Math.sqrt( dx*dx + dy*dy ); return dist; }; /* Config */ var minX = 0; var maxX = window.innerWidth; var minY = 0; var maxY = window.innerHeight; /* Proper Lightning */ function TargetedLightning(trailSize, target){ var self = this; self.px = 0; self.py = 0; self.color = new Color(128); self.target = target; self.trailSize = trailSize; self.trail = []; for(var i = 0; i < self.trailSize; i++){ self.trail.push({px: self.px, py: self.py}); } self.jumpLength = 15; self.deltaJumpLength = 15; self.disturbLength = self.jumpLength * 2/ 3; self.deltaDisturbLength = self.deltaJumpLength * 2 / 3; // Anything with a px and py values self.setTarget = function(target){ self.target = target; }; self.update = function(){ var dxTarget = self.target.px - self.px; var dyTarget = self.target.py - self.py; var dist = distance2dPositions(dxTarget, dyTarget); var randomAngle = Math.random() * Math.PI; var disturbLength = self.disturbLength + Math.random() * self.deltaDisturbLength; var jumpLength = self.jumpLength + self.deltaJumpLength * Math.random(); // if close enough, goes exatly to the target. No disturbances! if(dist < (self.jumpLength + self.deltaJumpLength)){ disturbLength = 0; jumpLength = dist; self.reachTarget(); } var finalDx = ((dxTarget / dist) * jumpLength ) + disturbLength * Math.cos(randomAngle); var finalDy = ((dyTarget / dist) * jumpLength ) + disturbLength * Math.sin(randomAngle); self.px += finalDx; self.py += finalDy; self.trail.pop(); self.trail.unshift({px: self.px, py: self.py}); }; self.draw = function(ctx){ ctx.beginPath(); ctx.moveTo(self.px, self.py); for(var i = 0; i < self.trail.length; i++){ ctx.lineTo(self.trail[i].px, self.trail[i].py); } ctx.strokeStyle = self.color.style; ctx.lineWidth = 3; ctx.stroke(); ctx.beginPath(); //ctx.moveTo(self.target.px, self.target.py); ctx.arc(self.target.px, self.target.py, 10, 0, Math.PI * 2, false); ctx.strokeStyle = this.color.style; ctx.stroke(); }; // Selects a new target position self.reachTarget = function(){ var newTarget = { px: Math.random() * maxX, py: Math.random() * maxY }; self.setTarget(newTarget); } }; $(function(){ var self = this; self.canvas = document.querySelector('canvas'); self.ctx = self.canvas.getContext('2d'); self.canvas.width = window.innerWidth; self.canvas.height = window.innerHeight; self.lightnings = []; self.updateAll = function(){ for(var i = 0; i < self.lightnings.length; i++){ self.lightnings[i].update(); } }; self.drawAll = function(){ for(var i = 0; i < self.lightnings.length; i++){ self.lightnings[i].draw(self.ctx); } }; self.animationCycle = function(){ self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height); self.updateAll(); self.drawAll(); requestAnimationFrame(self.animationCycle); }; self.initApp = function(){ for(var i = 0; i < 2; i++){ self.lightnings.push(new TargetedLightning(15, {px: self.canvas.width / 2, py: self.canvas.height / 2})); } }; self.initApp(); requestAnimationFrame(self.animationCycle); });