From 89a963e30bc6a139b84ec65e095f3628ff5494fc Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Fri, 27 Oct 2023 02:07:48 -0700 Subject: [PATCH] Starfield tweaks --- src/starfield/reference.ts | 2 + src/starfield/starfield.ts | 105 ++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/starfield/reference.ts b/src/starfield/reference.ts index e4523a2..be9f9c8 100644 --- a/src/starfield/reference.ts +++ b/src/starfield/reference.ts @@ -45,9 +45,11 @@ export function reference(canvas, ctx) { if (!start) start = timestamp var progress = timestamp - start + console.log("progress", progress); // Create a new star if it's been long enough since // the previous one timeSinceLastStar += progress + console.log('timesince', timeSinceLastStar); if (timeSinceLastStar > starInterval) { timeSinceLastStar = 0 makeStar() diff --git a/src/starfield/starfield.ts b/src/starfield/starfield.ts index d8fcce8..b454cba 100644 --- a/src/starfield/starfield.ts +++ b/src/starfield/starfield.ts @@ -17,4 +17,107 @@ function resize() { window.addEventListener('resize', resize, false); -reference(canvas, ctx); + +class Star { + // Star x and y are offsets from center of screen + constructor(x: number, y: number, multiplier: number) { + this.x = x; + this.y = y; + this.multiplier = multiplier; + } + + canvasPos() { + return { + x: (canvas.width / 2) + this.x, + y: (canvas.height / 2) + this.y, + }; + } + + size() { + // Size is proportional to distance from the middle + //const dist = Math.max(this.x, this.y); + //return Math.max(1.5, dist/100); + return 1.0; + } + + render(ctx) { + const { x, y } = this.canvasPos(); + const r = this.size(); + ctx.fillStyle = "red"; + ctx.beginPath(); + ctx.arc(x, y, r, 0, 2*Math.PI) + ctx.fill(); + } + + static make() { + const angle = Math.random() * 2*Math.PI + const x = Math.cos(angle); + const y = Math.sin(angle); + // The multiplier affects how quickly the star moves. + // Varying this makes some stars appear closer (faster + // movement), some further (slower movement). + const multiplier = 1.01 + Math.random() * 0.04; + return new Star(x, y, multiplier); + } +}; + +const state = { + start: null, + stars: [], + timeSinceLastStar: Infinity, +}; + +let start = null; +let stars = []; +let timeSinceLastStar = Infinity; + +const starIntervalms = 2000; +const fadeout = 8 / 100; + +function clear(ctx, alpha) { + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = `rgba(0,0,0, ${alpha})`; + ctx.fillRect( 0, 0, canvas.width, canvas.height ); + ctx.globalCompositeOperation = "lighter"; +} + +function loop(timestamp) { + if (state.start === null) { + state.start = timestamp; + } + const progress = timestamp - state.start + + // Create a new star if it's been long enough since + // the previous one + state.timeSinceLastStar += progress; + if (state.timeSinceLastStar > starIntervalms) { + state.timeSinceLastStar = 0 + state.stars.push(Star.make()); + } + + // Clear the screen. + // If you want the hyperspace effect, skip this. + clear(ctx, fadeout); + + state.stars.forEach((star) => { + // Increase the star's distance from the middle + // proportionally to its current distance + const multiplier = star.multiplier; + star.x *= multiplier + star.y *= multiplier + star.render(ctx); + }) + + // Remove stars outside the view boundary + let i = state.stars.length; + while (--i) { + const star = state.stars[i]; + let {x, y} = star.canvasPos(); + if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) { + state.stars.splice(i, 1) + } + } + window.requestAnimationFrame(loop) +} +window.requestAnimationFrame(loop) +//reference(canvas, ctx);