Cycle rain streams through the sprite pool for a sense of change
Test, Build and Push / test-gateway (push) Successful in 10s
Test, Build and Push / release (push) Skipped
Test, Build and Push / build-gateway (push) Skipped

Each stream periodically swaps to a different one of the pooled streak
sprites on a staggered timer, so the columns keep changing rather than
sitting statically tiled — the rain reads as alive in the corner of the
eye. The pool stays at 5: each sprite is ~15 KB of internal RAM and more
starves esp-hosted's internal-RAM task stacks into a boot loop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKPbR6DY2JygHbyLjxm7Uu
This commit is contained in:
2026-07-15 18:34:17 +02:00
co-authored by Claude Opus 4.8
parent b42d8216cc
commit ebdb1f0457
+10 -1
View File
@@ -32,7 +32,9 @@ LV_FONT_DECLARE(font_rage_64);
#define SPRITE_GLYPHS 12 /* streak length in a sprite */
#define SPRITE_W 24 /* sprite width (glyph ~22px) */
#define SPRITE_H (SPRITE_GLYPHS * CELL_H)
#define SPRITE_POOL 5 /* distinct pre-rendered streaks */
#define SPRITE_POOL 5 /* distinct pre-rendered streaks. Capped at 5:
* each ~15 KB in internal RAM, and more starves
* esp-hosted's internal-RAM task stacks (boot loop). */
#define RAIN_COLS (SCREEN / RAIN_CELL)
#define TICK_MS 33
@@ -89,6 +91,7 @@ static const char *GLYPHS[] = {
typedef struct {
lv_obj_t *img; /* lv_image showing one of the pool sprites */
int sprite; /* which pool sprite (index into sprite_dsc) */
int flip_in; /* ticks until this stream swaps to another pool sprite */
int x, y, speed;
bool alive;
} stream_t;
@@ -174,6 +177,7 @@ static void stream_spawn(stream_t *s, int speed)
s->speed = speed + esp_random() % 4;
s->y = -SPRITE_H;
s->sprite = esp_random() % SPRITE_POOL;
s->flip_in = 12 + esp_random() % 28;
if (s->img == NULL) {
s->img = lv_image_create(F.rain_layer);
}
@@ -218,6 +222,11 @@ static void rain_tick(void)
alive++;
s->y += s->speed * 2; /* cheap blit of a pre-rendered sprite */
lv_obj_set_pos(s->img, s->x, s->y);
if (--s->flip_in <= 0) { /* swap to a different streak sprite: the "flip" */
s->sprite = (s->sprite + 1 + esp_random() % (SPRITE_POOL - 1)) % SPRITE_POOL;
lv_image_set_src(s->img, &sprite_dsc[s->sprite]);
s->flip_in = 12 + esp_random() % 28;
}
if (s->y > SCREEN) {
if (alive > target) {
stream_hide(s);