68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
import random
|
||
import utime
|
||
|
||
|
||
class Blizzard:
|
||
"""Dense falling flakes with sideways drift (compare `snowfall` for gentler flakes)."""
|
||
|
||
def __init__(self, driver):
|
||
self.driver = driver
|
||
|
||
def run(self, preset):
|
||
colors = preset.c if preset.c else [(255, 255, 255), (200, 230, 255), (180, 210, 255)]
|
||
# Higher n1 → more spawns (0–255 threshold vs random)
|
||
density = max(1, int(preset.n1) if int(preset.n1) > 0 else 90)
|
||
speed = max(1, int(preset.n2) if int(preset.n2) > 0 else 2)
|
||
# n3: 128 = no bias; <128 drift one way, >128 the other (scaled to small steps)
|
||
wraw = int(preset.n3)
|
||
if wraw <= 0:
|
||
wind = 0
|
||
else:
|
||
wind = max(-4, min(4, (wraw - 128) // 20))
|
||
|
||
flakes = []
|
||
last = utime.ticks_ms()
|
||
|
||
while True:
|
||
d_ms = max(1, int(preset.d))
|
||
now = utime.ticks_ms()
|
||
if utime.ticks_diff(now, last) >= d_ms:
|
||
nled = self.driver.num_leds
|
||
bg = self.driver.apply_brightness(preset.background_or(colors), preset.b)
|
||
|
||
for i in range(nled):
|
||
self.driver.n[i] = bg
|
||
|
||
if random.randint(0, 255) < density:
|
||
flakes.append(
|
||
[
|
||
nled - 1,
|
||
random.randint(0, len(colors) - 1),
|
||
0 if wind == 0 else random.randint(-1, 1),
|
||
]
|
||
)
|
||
|
||
nf = []
|
||
for pos, ci, wj in flakes:
|
||
p = pos
|
||
lateral = wind + (wj if wj else 0)
|
||
p -= self.driver.signed(preset, speed)
|
||
p += self.driver.signed(preset, lateral)
|
||
if p < -2 or p >= nled + 2:
|
||
continue
|
||
pi = max(0, min(nled - 1, int(p)))
|
||
self.driver.n[self.driver.led_i(preset, pi)] = self.driver.apply_brightness(
|
||
colors[ci], preset.b
|
||
)
|
||
nf.append([p, ci, wj])
|
||
flakes = nf
|
||
|
||
self.driver.n.write()
|
||
last = utime.ticks_add(last, d_ms)
|
||
|
||
if not preset.a:
|
||
yield
|
||
return
|
||
|
||
yield
|