-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstarfall.js
112 lines (85 loc) · 2.31 KB
/
starfall.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const starfallCanvas = document.getElementById("starfallCanvas")
starfallCanvas.width = window.innerWidth
starfallCanvas.height = window.innerHeight
const starfallCtx = starfallCanvas.getContext("2d")
class Starfall {
constructor() {
this.pos = {x: 0, y: 0}
this.vel = {x: 0, y: 0}
}
generate() {
const dir = randomBool(0.5)
this.pos.x = dir ? -50 : pxWidth + 50
this.pos.y = randomInt(-starfallCanvas.height / 2, starfallCanvas.height / 2)
this.vel.x = dir ? randomFloat(3, 6) : randomFloat(-6, -3)
this.vel.y = randomFloat(0.25, 1)
}
draw() {
// very expensive but idk how to make it less expensive
drawPixelLine(
this.pos.x,
this.pos.y,
this.pos.x - (this.vel.x * 5),
this.pos.y - (this.vel.y * 5)
)
}
stepAnimation() {
this.pos.x += this.vel.x
this.pos.y += this.vel.y
}
}
function drawPixelLine(fromX, fromY, toX, toY) {
const pxInflate = 0.1
const dx = Math.abs(toX - fromX)
const dy = Math.abs(toY - fromY)
const sx = fromX < toX ? 1 : -1
const sy = fromY < toY ? 1 : -1
let err = dx - dy
let x = fromX
let y = fromY
starfallCtx.beginPath()
const steps = Math.max(dx, dy)
for (let i = 0; i <= steps; i++) {
const alpha = i == 0 ? 1 : 0.1 * (1 - i / steps)
starfallCtx.fillStyle = `rgba(255, 255, 255, ${alpha})`
starfallCtx.rect(
clampNearest(x * pxDensity, pxDensity) - 0.5,
clampNearest(y * pxDensity, pxDensity) - 0.5,
pxInflate + pxDensity,
pxInflate + pxDensity
)
const e2 = 2 * err
if (e2 > -dy) {
err -= dy
x += sx
}
if (e2 < dx) {
err += dx
y += sy
}
starfallCtx.fill()
}
}
let allStarfalls = []
function animateStarfalls() {
if (!isAnimating) { return }
starfallCtx.clearRect(0, 0, starfallCanvas.width, starfallCanvas.height)
let shouldGenerate = randomBool(0.01)
if (shouldGenerate) {
let newStarfall = new Starfall()
newStarfall.generate()
allStarfalls.push(newStarfall)
}
for (let starfall of allStarfalls) {
if (starfall.pos.x < -50 || starfall.pos.x > pxWidth + 50) {
allStarfalls.splice(allStarfalls.indexOf(starfall), 1)
continue
}
starfall.stepAnimation()
starfall.draw()
}
}
function startStarfall() {
animateStarfalls()
requestAnimationFrame(startStarfall)
}