Game math & UI, rung — panel HUD: a status box that survives a dialog. More...
Macros | |
| #define | BG1_CHR 0x0000 |
| #define | BG1_MAP 0x1000 |
| #define | BG2_CHR 0x2000 |
| #define | BG2_MAP 0x4400 |
| #define | BORDER_IDX 2 /* box border */ |
| #define | BOX_PAL 1 |
| #define | DLG_H 7 |
| #define | DLG_W 24 |
| #define | DLG_X 4 |
| #define | DLG_Y 20 |
| #define | EMPTY_IDX 4 /* empty-heart grey */ |
| #define | FILL_IDX 1 /* box interior */ |
| #define | HEART_IDX 3 /* heart red */ |
| #define | HUD_H 3 |
| #define | HUD_W 14 |
| #define | HUD_X 1 |
| #define | HUD_Y 1 |
| #define | MAX_HP 5 |
| #define | SHEET_BASE 1 /* top-left corner of the 3x3 border */ |
| #define | SHEET_STRIDE 3 |
| #define | TILE_BLANK 0 |
| #define | TILE_HEART 10 /* icons live past the 9-slice */ |
| #define | TILE_HEART_EMPTY 11 |
Functions | |
| static void | build_border (u8 top, u8 bottom, u8 left, u8 right) |
| Build one 9-slice border tile: border on the named edges, fill else. | |
| static void | build_heart (u8 filled) |
| Build a heart icon on the box-fill background (filled or outline). | |
| static void | build_scene (void) |
| A colourful BG1 scene so the HUD clearly floats over content. | |
| static void | build_sheet (void) |
| Build the whole BG2 sheet: blank, 9-slice, two heart icons. | |
| static void | draw_hearts (void) |
| Redraw the heart row inside the HUD from hero_hp. | |
| static void | flush_hud_row (void) |
| Push ONLY the HUD's heart row to VRAM — a small VBlank-safe DMA. | |
| int | main (void) |
| static void | put_tile (u16 tile) |
| Upload the just-encoded tile to a tile slot in BG2's char space. | |
Variables | |
| u8 | dialog_shown |
| Probe oracle: 1 while the dialog box is open. | |
| u8 | hero_hp |
| Probe oracle: current hearts shown (0..MAX_HP). | |
| static u16 | panel_map [32 *32] |
| The panel tilemap — caller-owned (the module never allocates 2 KB). | |
| static u8 | px [64] |
| Scratch: one 8x8 tile as pixel indices, then packed to 4bpp. | |
| static u8 | tilebuf [32] |
| static const Panel | ui |
| The panel: HUD + dialog share this one layer and one upload. | |
Game math & UI, rung — panel HUD: a status box that survives a dialog.
Every game needs furniture: a status bar with hearts and a coin count, a dialog box that opens over the world and closes again. Both are the same primitive — a 9-slice panel, a bordered box stamped from a 3x3 tile sheet (four corners, four edges, one fill) onto a background layer. The panel module does the stamping; you own the tilemap.
Its whole point is on show here: the HUD and the dialog live in ONE tilemap on ONE layer. Opening the dialog (panelDraw + panelFlush) and closing it (panelClear + panelFlush) never disturbs the HUD.
panelFlush() uploads the whole 2 KB map under FORCED BLANK, which briefly blanks the screen — fine for a structural change like a dialog box, but far too heavy to run every time a heart changes. So the hearts, which change often, upload only their own 64-byte tilemap row with an ordinary VBlank DMA (flush_hud_row) — no forced blank, no flicker. The rule: panelFlush for structure, a small VBlank DMA for frequent HUD tweaks.
The border and heart icons are generated in C — zero assets. Tile 0 is left transparent (that is what panelInit() stamps everywhere), so the colourful BG1 shows through wherever no panel has been drawn.
ROM mode: LoROM (project default).
| #define BG1_CHR 0x0000 |
BG1 scene tiles
| #define BG1_MAP 0x1000 |
BG1 tilemap
| #define BG2_CHR 0x2000 |
BG2 panel sheet tiles
| #define BG2_MAP 0x4400 |
BG2 panel tilemap (uploaded by panelFlush)
| #define BORDER_IDX 2 /* box border */ |
| #define BOX_PAL 1 |
| #define DLG_H 7 |
| #define DLG_W 24 |
| #define DLG_X 4 |
| #define DLG_Y 20 |
| #define EMPTY_IDX 4 /* empty-heart grey */ |
| #define FILL_IDX 1 /* box interior */ |
| #define HEART_IDX 3 /* heart red */ |
| #define HUD_H 3 |
| #define HUD_W 14 |
| #define HUD_X 1 |
| #define HUD_Y 1 |
| #define MAX_HP 5 |
| #define SHEET_BASE 1 /* top-left corner of the 3x3 border */ |
| #define SHEET_STRIDE 3 |
| #define TILE_BLANK 0 |
| #define TILE_HEART 10 /* icons live past the 9-slice */ |
| #define TILE_HEART_EMPTY 11 |
Build one 9-slice border tile: border on the named edges, fill else.
| top,bottom,left,right | 1 if this tile carries that edge. |
|
static |
Build a heart icon on the box-fill background (filled or outline).
|
static |
A colourful BG1 scene so the HUD clearly floats over content.
< BG1 scene tiles
< BG1 tilemap
|
static |
Build the whole BG2 sheet: blank, 9-slice, two heart icons.
|
static |
Redraw the heart row inside the HUD from hero_hp.
|
static |
Push ONLY the HUD's heart row to VRAM — a small VBlank-safe DMA.
The hearts change often (every hit), so they must not pay panelFlush()'s 2 KB forced-blank cost — that would blank the top of the screen for a frame on every change. One tilemap row is 64 bytes, which fits the VBlank budget with room to spare, so we upload just that row with no forced blank. panelFlush() stays for structural changes (opening the dialog).
< BG2 panel tilemap (uploaded by panelFlush)
| int main | ( | void | ) |
< BG1 scene tiles
< BG1 tilemap
< BG2 panel sheet tiles
< BG2 panel tilemap (uploaded by panelFlush)
|
static |
Upload the just-encoded tile to a tile slot in BG2's char space.
< BG2 panel sheet tiles
| u8 dialog_shown |
Probe oracle: 1 while the dialog box is open.
| u8 hero_hp |
Probe oracle: current hearts shown (0..MAX_HP).
|
static |
The panel tilemap — caller-owned (the module never allocates 2 KB).
|
static |
Scratch: one 8x8 tile as pixel indices, then packed to 4bpp.
|
static |