Vary glitch band positions across loop cycles; soften corner ticks

GLITCH_STATES was a fixed list of 4 band configs that every repeat cycle
played identically, so the jitter looked the same each time it looped.
Expanded to an 8-entry GLITCH_STATE_POOL and rotate through a different
4-state window each cycle (wrapping back to the start via modular
indexing, since Starlark list slicing doesn't wrap) -- verified via an
isolated two-cycle test that cycle 2's band positions genuinely differ
from cycle 1's, not just coincidentally similar-looking.

Also added alpha transparency to the corner tick color (#33ff9980) so
they read as a subtle HUD accent rather than a solid opaque overlay.
This commit is contained in:
poprhythm committed 2026-10-08 17:17:49 -04:00
1 parent 78621b3831
commit 1d5c86fb61
1 file changed
+27 -6
+27 -6
View File
@@ -357,12 +357,25 @@ def _zoomed_art(art_bytes, zoom_scale, zoom_position, subsonic_id):
# middle band, each about 30% of the frame's height. # middle band, each about 30% of the frame's height.
GLITCH_HOLD_TICKS = 5 # ~250ms per jitter state at the default 50ms/tick GLITCH_HOLD_TICKS = 5 # ~250ms per jitter state at the default 50ms/tick
GLITCH_PAUSE_TICKS = 15 # ~750ms of clean art between bursts GLITCH_PAUSE_TICKS = 15 # ~750ms of clean art between bursts
GLITCH_STATES = [ GLITCH_STATES_PER_CYCLE = 4
# (top1, height1, shift1, hue1, top2, height2, shift2, hue2)
# A larger pool than any one burst needs, so repeated cycles (see
# GLITCH_REPEATS below) draw a different rotating window of states each
# time instead of showing the identical 4 band positions every loop.
# (top1, height1, shift1, hue1, top2, height2, shift2, hue2); proportions
# loosely modeled on the one SUB/WAVE keyframe that was visible (roughly
# the top third and an overlapping middle band, each ~30% of the frame's
# height) -- see the note above GLITCH_HOLD_TICKS for why that's the only
# part grounded in anything observed rather than invented.
GLITCH_STATE_POOL = [
(3, 9, -2, 150.0, 19, 8, 2, -60.0), (3, 9, -2, 150.0, 19, 8, 2, -60.0),
(2, 8, 2, 150.0, 20, 9, -3, -60.0), (2, 8, 2, 150.0, 20, 9, -3, -60.0),
(5, 7, -3, 150.0, 17, 10, 1, -60.0), (5, 7, -3, 150.0, 17, 10, 1, -60.0),
(1, 10, 1, 150.0, 21, 7, -2, -60.0), (1, 10, 1, 150.0, 21, 7, -2, -60.0),
(6, 6, 1, 150.0, 14, 9, 3, -60.0),
(0, 8, 3, 150.0, 24, 6, -1, -60.0),
(4, 7, -1, 150.0, 12, 10, 2, -60.0),
(2, 9, -3, 150.0, 22, 7, 1, -60.0),
] ]
# render.Sequence doesn't loop on its own (see _glitch_scanlines below), so # render.Sequence doesn't loop on its own (see _glitch_scanlines below), so
@@ -371,10 +384,18 @@ GLITCH_STATES = [
# rather than relying on any runtime looping. Rounds up so the window is # rather than relying on any runtime looping. Rounds up so the window is
# always fully covered, even if that runs a little past # always fully covered, even if that runs a little past
# STATIC_OVERLAY_SECONDS -- better than the jitter cutting out early. # STATIC_OVERLAY_SECONDS -- better than the jitter cutting out early.
_GLITCH_CYCLE_TICKS = len(GLITCH_STATES) * GLITCH_HOLD_TICKS + GLITCH_PAUSE_TICKS _GLITCH_CYCLE_TICKS = GLITCH_STATES_PER_CYCLE * GLITCH_HOLD_TICKS + GLITCH_PAUSE_TICKS
_GLITCH_TICKS_PER_SECOND = 20 # 1000ms / 50ms-per-tick _GLITCH_TICKS_PER_SECOND = 20 # 1000ms / 50ms-per-tick
GLITCH_REPEATS = int(STATIC_OVERLAY_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1 GLITCH_REPEATS = int(STATIC_OVERLAY_SECONDS * _GLITCH_TICKS_PER_SECOND / _GLITCH_CYCLE_TICKS) + 1
def _glitch_states_for_cycle(cycle_index):
# Rotate through GLITCH_STATE_POOL instead of slicing (which doesn't
# wrap around in Starlark), so each cycle's window of states can
# straddle the end of the pool and loop back to the start.
pool_size = len(GLITCH_STATE_POOL)
start = (cycle_index * GLITCH_STATES_PER_CYCLE) % pool_size
return [GLITCH_STATE_POOL[(start + i) % pool_size] for i in range(GLITCH_STATES_PER_CYCLE)]
def _glitch_band(zoomed_art, top, height, shift_x, hue_change): def _glitch_band(zoomed_art, top, height, shift_x, hue_change):
tinted = filter.Hue(child = zoomed_art, change = hue_change) tinted = filter.Hue(child = zoomed_art, change = hue_change)
band = render.Padding( band = render.Padding(
@@ -410,8 +431,8 @@ def _glitch_jitter(zoomed_art):
pause = _glitch_hold(render.Box(width = ART_SLOT, height = ART_SLOT), GLITCH_PAUSE_TICKS) pause = _glitch_hold(render.Box(width = ART_SLOT, height = ART_SLOT), GLITCH_PAUSE_TICKS)
sequence = [] sequence = []
for _ in range(GLITCH_REPEATS): for cycle_index in range(GLITCH_REPEATS):
for top1, h1, shift1, hue1, top2, h2, shift2, hue2 in GLITCH_STATES: for top1, h1, shift1, hue1, top2, h2, shift2, hue2 in _glitch_states_for_cycle(cycle_index):
state = render.Stack(children = [ state = render.Stack(children = [
_glitch_band(zoomed_art, top1, h1, shift1, hue1), _glitch_band(zoomed_art, top1, h1, shift1, hue1),
_glitch_band(zoomed_art, top2, h2, shift2, hue2), _glitch_band(zoomed_art, top2, h2, shift2, hue2),
@@ -486,7 +507,7 @@ def _glitch_effect(zoomed_art):
child = render.Stack(children = [ child = render.Stack(children = [
_glitch_jitter(zoomed_art), _glitch_jitter(zoomed_art),
_glitch_scanlines(), _glitch_scanlines(),
_glitch_corner_ticks("#33ff99"), _glitch_corner_ticks("#33ff9980"),
]), ]),
) )
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.