From 91ebe149046fae3b075f7ea5bfa7b1532c9bc7c5 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sat, 15 Dec 2018 03:06:01 +0300 Subject: starfield, need to figure out algorithm --- starfield/stars.html | 36 ++++++++++ starfield/stars.js | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 starfield/stars.html create mode 100644 starfield/stars.js diff --git a/starfield/stars.html b/starfield/stars.html new file mode 100644 index 0000000..e763898 --- /dev/null +++ b/starfield/stars.html @@ -0,0 +1,36 @@ + + + + + Starfield demo + + + + + + + + + diff --git a/starfield/stars.js b/starfield/stars.js new file mode 100644 index 0000000..373b934 --- /dev/null +++ b/starfield/stars.js @@ -0,0 +1,185 @@ +/* +Starfield JS v0.0.1 +Copyright 2018 Yaroslav de la Peña Smirnov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the disclaimer +below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +function Particle(ix, iy, posz){ + this.ix = ix; + this.iy = iy; + this.posz = posz; +} + +function warpLaunch(options={}){ + /* >>> Some parameters <<< */ + var max_particles = + options.hasOwnProperty('max_particles') ? options['max_particles'] : 1000; + var speed = + options.hasOwnProperty('speed') ? options['speed'] : 30; + + var canvas = document.getElementById("stars"); + if(!canvas){ + console.log("There is no '#stars' canvas to draw on! Aborting..."); + return; + } + var container = canvas.parentNode; + var ctx = canvas.getContext("2d"); + + // The canvas where we will prerender our star + var starsprite = document.createElement("canvas"); + + // This will be populated with all the 'particles' (i.e. snowflakes) + // on the canvas + var particles = []; + var last = null; // previous timestamp + var requestedFrame; + + function randomRange(min, max){ + return Math.floor(Math.random() * (max - min - 1)) + min; + } + + function randomInt(max){ + return Math.floor(Math.random() * max); + } + + function resize(){ + // On window/viewport resize, get the new size of the container + // and accordingly resize the canvas, then reinitialize + canvas.height = parseInt(container.offsetHeight); + canvas.width = parseInt(container.offsetWidth); + try{ window.cancelAnimationFrame(requestedFrame); } + catch(e) {} + ctx.imageSmoothingEnabled = false; + ctx.webkitImageSmoothingEnabled = false; + ctx.mozImageSmoothingEnabled = false; + ctx.save(); + initParticles(); + } + + /*function prerender(){ + let sctx = starsprite.getContext("2d"); + sctx.imageSmoothingEnabled = false; + sctx.webkitImageSmoothingEnabled = false; + starsprite.width = 8; + starsprite.height = 8; + sctx.fillStyle = "rgb(255, 255, 255, 0.5)"; + sctx.fillRect(0, 3, 8, 2); + sctx.fillRect(3, 0, 2, 8); + sctx.fillRect(2, 2, 4, 4); + }*/ + + function prerender(){ + let sctx = starsprite.getContext("2d"); + sctx.imageSmoothingEnabled = false; + sctx.webkitImageSmoothingEnabled = false; + starsprite.width = 5; + starsprite.height = 5; + sctx.fillStyle = "rgb(255, 255, 255, 0.4)"; + sctx.fillRect(0, 2, 5, 1); + sctx.fillRect(2, 0, 1, 5); + sctx.fillStyle = "rgb(255, 255, 255, 0.5)"; + sctx.fillRect(1, 1, 3, 3); + } + + function getRandomPos(n){ + let i = randomRange(-n, n); + if (i == 0) return getRandomPos(); + return i; + } + + function getNewParticle(){ + // Randomly assign them the needed parameters + let halfWidth = canvas.width/2; + let halfHeight = canvas.height/2; + //let ix = getRandomPos(halfWidth/20); + //let iy = getRandomPos(halfHeight/20); + let ix = getRandomPos(5); + let iy = getRandomPos(5); + let posz = randomRange(50, 200); + return new Particle(ix, iy, posz); + } + + function initParticles(){ + for (let i = 0; i < max_particles; ++i){ + let particle = getNewParticle(); + particles.push(particle); + drawStar(particle); + } + requestedFrame = window.requestAnimationFrame(nextFrame); + } + + function drawStar(particle){ + let scale = particle.posz/100; + let p = scale/2; + let halfWidth = canvas.width/2; + let halfHeight = canvas.height/2; + let posx = (particle.ix+halfWidth*particle.ix)*p; + let posy = (particle.iy+halfHeight*particle.iy)*p; + ctx.globalAlpha = p; + ctx.translate(posx, posy); + ctx.scale(scale, scale); + ctx.drawImage(starsprite, 0, 0); + ctx.restore(); + ctx.save(); + } + + function nextFrame(timestamp){ + if (!last) last = timestamp; + let delta = timestamp - last; + // If more than 250ms have passed since last frame, it is assumed + // that the browser stopped calling back frames because the tab/page + // was in the background, thus this frame is ignored, and the last + // timestamp reset + if (delta > 250){ + last = timestamp; + requestedFrame = window.requestAnimationFrame(nextFrame); + return; + } + ctx.clearRect(0, 0, canvas.width, canvas.height); + for(let i = 0; i < max_particles; i++){ + let particle = particles[i]; + particle.posz += delta*speed/1000; + if (particle.posz > 200){ + particle = getNewParticle(); + particle.posz = 50; + particles[i] = particle; + } + drawStar(particle); + } + last = timestamp; + requestedFrame = window.requestAnimationFrame(nextFrame); + } + + prerender(); + resize(); + + window.addEventListener("resize", resize); +} -- cgit v1.2.3