joeylib2/examples/spacetaxi/stHud.c

79 lines
3.2 KiB
C

// Space Taxi -- HUD (score / lives / level / current-fare strip).
//
// Lives in the bottom 3 tile-rows (y = 176..199) below the playfield.
// Renders textual score / lives / level name / current fare via the
// font asset (loaded by stRender). No fuel meter: the C64 original
// has no fuel mechanic. The strip at $DBA2-$DBCB in the original game
// is a per-frame Y-velocity status indicator ($6419), not a fuel bar.
#include <stdio.h>
#include <string.h>
#include "spacetaxi.h"
JOEYLIB_SEGMENT("STAXI")
void stHudDraw(jlSurfaceT *stage, const StGameT *game) {
char buf[32];
char livesBuf[ST_MAX_PADS + 1];
uint8_t i;
// Wipe the HUD band with the level's border color (C64 $7D00 -> $D020).
// Most canonical levels set both border and bg to 0 (black), so this
// looks identical to the previous hardcoded ST_HUD_BG_COLOR for them.
jlFillRect(stage,
0,
(int16_t)(ST_HUD_ROW * ST_TILE_PIXELS),
SURFACE_WIDTH,
(int16_t)(ST_HUD_ROW_COUNT * ST_TILE_PIXELS),
game->level.borderColor);
// 4-digit score with a separator after the thousands digit, matching
// the C64 HUD template at $43B1 ('___ . __'). The format puts the
// ones digit at position 3 and uses '.' as a thousands marker. Range
// is 0..9999; beyond that we wrap (the C64 BCD can't exceed 9999
// either).
snprintf(buf, sizeof(buf), "%04lu.",
(unsigned long)(game->score % 10000ul));
stRenderDrawText(stage, 0u, (uint8_t)ST_HUD_ROW, buf);
// Lives indicator: graphic-ish "cabs remaining" -- one 'O' per life,
// up to 9. C64 shows this as filled glyphs in color RAM ($DBDC etc).
for (i = 0u; i < 9u && i < game->lives; i++) {
livesBuf[i] = 'O';
}
livesBuf[i] = '\0';
stRenderDrawText(stage, 7u, (uint8_t)ST_HUD_ROW, livesBuf);
// Level name right-aligned in the 40-col HUD row.
{
uint8_t nameLen = (uint8_t)strlen(game->level.name);
uint8_t col = (nameLen < ST_TILEMAP_W)
? (uint8_t)(ST_TILEMAP_W - nameLen)
: 0u;
stRenderDrawText(stage, col, (uint8_t)ST_HUD_ROW, game->level.name);
}
// Active fare display: where the current passenger wants to go
// (or "PAD x WANTS y" when one is still waiting to be picked up).
for (i = 0u; i < ST_MAX_PASSENGERS; i++) {
const StPassengerT *p = &game->passengers[i];
if (p->active && p->onboard &&
p->destPad < game->level.padCount) {
char dest = (char)game->level.pads[p->destPad].letter;
snprintf(buf, sizeof(buf), "FARE %c", dest);
stRenderDrawText(stage, 0u, (uint8_t)(ST_HUD_ROW + 1u), buf);
break;
}
if (p->active && !p->onboard &&
p->currentPad < game->level.padCount) {
char src = (char)game->level.pads[p->currentPad].letter;
char dest = (p->destPad < game->level.padCount)
? (char)game->level.pads[p->destPad].letter : '?';
snprintf(buf, sizeof(buf), "PAD %c WANTS %c", src, dest);
stRenderDrawText(stage, 0u, (uint8_t)(ST_HUD_ROW + 1u), buf);
break;
}
}
}