Public Access
Game of Life page element and built-in page
A new page element runs Conway's Game of Life in an area (the whole display by default), one per page. Start: random dots, one pattern, or the icons whose names start with a text in turn or in random order. Edges: wrap around, dead, or a hidden margin where gliders fly out of view (leftovers that stay put in the margin are cleared, so a glider gun runs cleanly). It restarts when the board is still or repeats within 16 generations and/or after a number of generations, after a hold time (an empty board at once). logic/life holds the board and timing (tested), display/life_player runs the board of the shown page, ticked before each frame; frames are paced like scrolling text. The element reuses existing fields, so the page format stays the same. The Icons tab has a library of 17 LifeWiki patterns (checked with a simulation), and the built-in page "Game of Life" shuffles through the life_ icons. About 12 KB flash, 8 KB RAM. Version 2.17.0, tested on the display over OTA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
948087077d
commit
a91d2550d7
29 files changed
+1402
-31
No files matched your search
@@ -156,6 +156,62 @@ static void drawBar(const PageElement &e, PageResources &resources, uint8_t *bit
|
||||
drawBarPercent(e, resources, bitmap, left + inner, e.y + inner, w - 2 * inner, h - 2 * inner);
|
||||
}
|
||||
|
||||
// Life without a running board (a preview of a page that is not shown): the start, the
|
||||
// pattern in the middle or a random fill that is always the same, in area coordinates
|
||||
static void lifeStart(const PageElement &e, int w, int h, PageResources &resources, uint8_t *start)
|
||||
{
|
||||
memset(start, 0, BITMAP_BYTES);
|
||||
uint32_t random = 1;
|
||||
uint8_t pattern[BITMAP_BYTES];
|
||||
int dx, dy;
|
||||
if (e.input_unit == LIFE_START_PATTERN)
|
||||
{
|
||||
if (!resources.background(e.text, pattern) || !lifePlacement(pattern, w, h, false, random, dx, dy))
|
||||
return;
|
||||
for (int y = 0; y < BITMAP_HEIGHT; y++)
|
||||
for (int x = 0; x < BITMAP_WIDTH; x++)
|
||||
if (bitmapPixel(pattern, x, y))
|
||||
setBitmapPixel(start, x + dx, y + dy, true);
|
||||
return;
|
||||
}
|
||||
int percent = e.input_unit == LIFE_START_RANDOM ? (int)e.factor : 30;
|
||||
for (int y = 0; y < h; y++)
|
||||
for (int x = 0; x < w; x++)
|
||||
setBitmapPixel(start, x, y, (int)(lifeRandom(random) % 100) < percent);
|
||||
}
|
||||
|
||||
// Life: the running board of the shown page; returns the ms until its next generation
|
||||
static uint32_t drawLife(const PageElement &e, uint32_t now_ms, PageResources &resources, uint8_t *bitmap,
|
||||
ElementBox &box)
|
||||
{
|
||||
int w = e.bar_width, h = e.bar_height;
|
||||
int left = e.x;
|
||||
if (e.align == Align::Center)
|
||||
left -= w / 2;
|
||||
else if (e.align == Align::Right)
|
||||
left -= w;
|
||||
box.x = left;
|
||||
box.y = e.y;
|
||||
box.width = w;
|
||||
box.height = h;
|
||||
if (e.overlay == Overlay::Box)
|
||||
clearBox(bitmap, left - 1, e.y - 1, w + 2, h + 2);
|
||||
|
||||
const LifeRunner *runner = resources.life(e);
|
||||
uint8_t start[BITMAP_BYTES];
|
||||
if (!runner)
|
||||
lifeStart(e, w, h, resources, start);
|
||||
for (int y = 0; y < h; y++)
|
||||
for (int x = 0; x < w; x++)
|
||||
{
|
||||
if (!(runner ? runner->board.cell(x, y) : bitmapPixel(start, x, y)))
|
||||
continue;
|
||||
int bx = left + x, by = e.y + y;
|
||||
setBitmapPixel(bitmap, bx, by, e.overlay == Overlay::Invert ? !bitmapPixel(bitmap, bx, by) : true);
|
||||
}
|
||||
return runner ? runner->msUntilNext(now_ms) : 0;
|
||||
}
|
||||
|
||||
// A text element; returns the ms until it scrolls on (0: it doesn't scroll)
|
||||
static uint32_t drawTextElement(const PageElement &e, const char *text, uint32_t now_ms, PageResources &resources,
|
||||
uint8_t *bitmap, ElementBox &box)
|
||||
@@ -223,6 +279,8 @@ uint32_t renderPage(const DynamicPage &page, const LocalTime &time, uint32_t now
|
||||
drawImage(e, resources, bitmap, box);
|
||||
else if (e.type == ElementType::Bar)
|
||||
drawBar(e, resources, bitmap, box);
|
||||
else if (e.type == ElementType::Life)
|
||||
next = sooner(next, drawLife(e, now_ms, resources, bitmap, box));
|
||||
else
|
||||
{
|
||||
ElementValues values;
|
||||
|
||||
Reference in new issue
Block a user