Toggle navigation
Sign Up
Log In
Explore
Works
Folders
Tools
Collections
Artists
Groups
Groups
Topics
Tasks
Tasks
Jobs
Teams
Jobs
Recommendation
More Effects...
JS
// even more awesome with this song playing ;) // https://www.youtube.com/watch?v=0NKUpo_xKyQ // ( lights ) 'use strict'; var w = c.width = window.innerWidth, h = c.height = window.innerHeight, ctx = c.getContext('2d'), opts = { hitLine: h - 30, hitIntensity: 1, hitCoolDown: 4, holeAttenuator: 30, repaintAlpha: 0.02, gravity: 0.01, meteorCount: 15, meteorSpawnProb: 0.05, meteorBaseSize: 10, meteorAddedSize: 10, meteorBaseVelX: 2, meteorAddedVelX: -4, meteorBaseVelY: 2, meteorAddedVelY: 3, meteorTemplateColor: 'hsl( hue, 80%, light% )', ashCount: 20, ashSpawnProb: 0.08, ashBaseSizeMultiplier: 0.1, ashAddedSizeMultiplier: 0.1, ashLifeMultiplier: 10 }, meteors = [], holes = [], explosions = 0, tick = 0, someAreDead = false, tau = Math.PI * 2; function init() { ctx.fillStyle = '#151515'; ctx.fillRect(0, 0, w, h); ctx.globalCompositeOperation = 'destination-out'; ctx.save(); meteors.length = 0; for (var i = 0; i < 100; ++i) loop_update(); loop(); } function loop() { window.requestAnimationFrame(loop); loop_update(); loop_render(); } function loop_update() { loop_update_tick(); loop_update_spawn(); meteors.map(function (meteor) { return meteor.update(); }); holes.map(function (hole, i) { return hole.dead ? holes.splice(i, 1) : hole.update(); }); } function loop_render() { loop_render_repaint(); loop_render_transform(); loop_render_hitLine(); ctx.globalCompositeOperation = 'lighter'; meteors.map(function (meteor) { return meteor.render(); }); holes.map(function (hole) { return hole.render(); }); } function loop_update_tick() { tick += 0.6; tick %= 360; if (explosions > 0) explosions -= 1 / opts.hitCoolDown; someAreDead = false; } function loop_update_spawn() { if (meteors.length < opts.meteorCount && Math.random() < opts.meteorSpawnProb) meteors.push(new Meteor()); } function loop_render_repaint() { ctx.restore(); ctx.fillStyle = 'rgba(0,0,0,alp)'.replace('alp', opts.repaintAlpha); ctx.fillRect(0, 0, w, opts.hitLine); if (someAreDead) { ctx.fillStyle = 'rgba(20,20,20,.1)'; // ctx.fillRect( 0, 0, w, h ); } ctx.save(); } function loop_render_transform() { ctx.translate(Math.random() * opts.hitIntensity * explosions, Math.random() * opts.hitIntensity * explosions); } function loop_render_hitLine() { ctx.fillStyle = 'rgba(20,20,20,alp)'.replace('alp', opts.repaintAlpha * 2); ctx.fillRect(0, opts.hitLine, w, h - opts.hitLine); } function Meteor() { this.reset(); } Meteor.prototype.reset = function () { this.x = Math.random() * w; this.y = 0; this.vx = opts.meteorBaseVelX + Math.random() * opts.meteorAddedVelX; this.vy = opts.meteorBaseVelY + Math.random() * opts.meteorAddedVelY; this.size = opts.meteorBaseSize + Math.random() * opts.meteorAddedSize | 0; this.y -= this.size; this.ashes = []; this.color = opts.meteorTemplateColor.replace('hue', tick); }; Meteor.prototype.update = function () { this.x += this.vx; this.y += this.vy += opts.gravity; this.update_ashes(); this.update_checkDead(); }; Meteor.prototype.render = function () { var color = opts.meteorTemplateColor.replace('hue', this.x / w * 100 + tick); ctx.fillStyle = color.replace('light', Math.random() * 30 + 25); ctx.shadowColor = color.replace('light', Math.random() * 25 + 25); ctx.shadowBlur = this.size; ctx.beginPath(); ctx.arc(this.x | 0, this.y | 0, this.size / 2, 0, tau); ctx.fill(); ctx.fillStyle = ctx.shadowColor; this.render_ashes(); }; Meteor.prototype.update_ashes = function () { if (this.ashes.length < opts.ashCount && Math.random() < opts.ashSpawnProb) this.ashes.push(new Ash(this)); this.ashes.map(function (ash) { return ash.update(); }); }; Meteor.prototype.update_checkDead = function () { if (this.x > w + this.size) this.reset(); if (this.y > opts.hitLine) this.update_checkDead_explode(); }; Meteor.prototype.update_checkDead_explode = function () { ++explosions; someAreDead = true; holes.push(new Hole(this)); this.reset(); }; Meteor.prototype.render_ashes = function () { this.ashes.map(function (ash) { return ash.render(); }); }; function Ash(meteor) { this.reset(meteor); } Ash.prototype.reset = function (meteor) { this.meteor = meteor; this.x = meteor.x + Math.random() * meteor.size * 2 - meteor.size | 0; this.y = meteor.y + Math.random() * meteor.size * 2 - meteor.size | 0; this.size = (opts.ashBaseSizeMultiplier + Math.random() * opts.ashAddedSizeMultiplier) * meteor.size | 0; this.life = this.originalLife = this.size * opts.ashLifeMultiplier | 0; }; Ash.prototype.update = function () { --this.life; if (this.life <= 0) this.reset(this.meteor); }; Ash.prototype.render = function () { ctx.fillRect(this.x, this.y, this.size, this.size); }; function Hole(meteor) { this.x = meteor.x; this.size = meteor.size * 10; this.color = 'hsla(hue, 80%, 55%, .04)'.replace('hue', this.x / w * 100 + tick); this.life = 0; } Hole.prototype.update = function () { this.life += (this.size - this.life) / opts.holeAttenuator; if (this.life > this.size * 0.6) this.dead = true; }; Hole.prototype.render = function () { ctx.shadowBlur = 0; ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, opts.hitLine, this.life, 0, tau); ctx.fill(); }; init();
CSS
canvas { position: absolute; top: 0; left: 0; background-color: #222; }
HTML
Join Effecthub.com
Working with Global Gaming Artists and Developers!
Login
Sign Up
Or Login with Your Email Address:
Email
Password
Remember
Or Sign Up with Your Email Address:
Your Email
This field must contain a valid email
Set Password
Password should be at least 1 character
Stay informed via email