Add four animated Cyberpunk-style ESPHome pages

Netrunner HUD, self-solving breach protocol, optics boot-and-scan and a
split HUD with a mini breach matrix, all in the page rotation. The el512
display gains animated_pages / animation_interval (redraw ~15 fps while
shown), page_age_ms() as animation clock, and shift_rows() / invert_rect()
for glitch effects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-18 23:29:12 +02:00
1 parent 6d5e5315f0
commit 50ee17b3f6
7 files changed
+944 -4

No files matched your search

+24
View File
@@ -1,5 +1,8 @@
#pragma once
#include <vector>
#include "cyberpunk.h"
#include "el512_helpers.h"
#include "el512_panel.h"
#include "esphome/components/display/display_buffer.h"
@@ -49,6 +52,21 @@ class EL512Display : public display::DisplayBuffer {
// When to start the music, in ms after the page was shown.
uint32_t still_alive_song_start_ms() const { return el512sa::StillAlivePlayer::songStartMs(); }
// Animated pages redraw every animation interval while they are shown,
// instead of once per update_interval. Their lambdas can use page_age_ms()
// as the animation clock.
void add_animated_page(display::DisplayPage *page) { this->animated_pages_.push_back(page); }
void set_animation_interval(uint32_t ms) { this->animation_interval_ = ms; }
// Time since the active page was shown, in ms.
uint32_t page_age_ms();
// millis() when the active page was shown (as seen by page_age_ms()).
uint32_t page_shown_at() const { return this->age_start_; }
// Effects on the drawing buffer, for use after drawing a page: shift rows
// y..y+height-1 right by dx pixels (wrapping around), invert a rectangle.
void shift_rows(int y, int height, int dx);
void invert_rect(int x, int y, int width, int height);
protected:
void draw_absolute_pixel_internal(int x, int y, Color color) override;
void check_refresh_health_();
@@ -66,6 +84,12 @@ class EL512Display : public display::DisplayBuffer {
display::DisplayPage *still_alive_return_{nullptr};
bool still_alive_was_active_{false};
el512sa::StillAlivePlayer still_alive_;
std::vector<display::DisplayPage *> animated_pages_;
uint32_t animation_interval_{66};
uint32_t animated_at_{0};
const display::DisplayPage *age_page_{nullptr};
uint32_t age_start_{0};
};
} // namespace esphome::el512