## CRT turn-on and turn-off animations ## Ported from AetherTune's Rust/ratatui implementation import illwill, os, times, math, std/random const # Turn-on phase timing (ms) OnFlashMs = 60 OnGlitchMs = 200 OnPhosphorMs = 500 OnStaticMs = 650 OnBeamMs = 1100 OnTotalMs = 1200 # Turn-off phase timing (ms) OffCollapseMs = 500 OffSqueezeMs = 800 OffDotMs = 1200 OffFadeMs = 1600 GlitchChars = ["█", "▓", "▒", "░", "▄", "▀", "■", "□", "╬", "╠", "╣", "═", "║", "·", ":", "!", "@", "#", "$", "%", "^", "&", "*"] NoiseChars = ["░", "▒", "▓", "│", "─", "┼", "╬", "·", ":", ";", "!", "?", "$", "#", "@", "%"] proc lcg(state: var uint64): uint64 = state = state * 6364136223846793005'u64 + 1'u64 result = state proc elapsedMs(start: Time): int = int((getTime() - start).inMilliseconds) proc brightColor(b: float): ForegroundColor = if b > 0.7: fgWhite elif b > 0.4: fgCyan else: fgGreen proc crtTurnOn*(tb: var TerminalBuffer, w, h: int) = let start = getTime() var rng = initRand(42) while true: let elapsed = elapsedMs(start) if elapsed >= OnTotalMs: break tb = newTerminalBuffer(w, h) if elapsed < OnFlashMs: # Phase 1: White flash — high-voltage discharge let c = if elapsed < OnFlashMs div 2: fgWhite else: fgCyan for y in 0..= OffFadeMs: break tb = newTerminalBuffer(w, h) if elapsed < OffCollapseMs: # Phase 1: Vertical collapse to center row let t = elapsed.float / OffCollapseMs.float let halfH = int((1.0 - t) * (h.float / 2.0)) for y in max(cy - halfH, 0).. 0.8: "▓" elif b > 0.6: "▒" elif b > 0.3: "░" else: "·" for x in 0.. 2: @[cy - 1, cy, cy + 1] else: @[cy] for y in rows: if y < 0 or y >= h: continue let isCentre = y == cy for x in max(cx - halfW, 0).. glowR.float: continue let (px, py) = (cx + dx, cy + dy) if px < 0 or px >= w or py < 0 or py >= h: continue let b = (1.0 - t * 0.3) * (1.0 - dist / glowR.float) let ch = if dx == 0 and dy == 0: "●" elif dist < glowR.float * 0.4: "░" else: "·" tb.write(px, py, brightColor(b), ch) else: # Phase 4: Fade to black let b = 1.0 - (elapsed - OffDotMs).float / (OffFadeMs - OffDotMs).float if b > 0.05: tb.write(cx, cy, (if b > 0.5: fgCyan else: fgGreen), "·") tb.display() sleep(16)