From 54e950141b963b9ff6e4fd8a019a63b51430477f Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 25 Jul 2026 11:46:46 +0200 Subject: [PATCH] HUD final: GAMEBAR.PCC pur (weisse Boxen), Original-Ziffern, 6 Herzen Stefans Korrektur: Box-Innenflaechen sind im Original WEISS (die Grafik hatte es schon richtig -- Dunkelrot-Fuellung entfernt, Grafik-":" damit nativ sichtbar). Zahlen jetzt in der Original-HUD-Font: GAMEBAR.BOB- Ziffern (7x13), gerendert mit der GAMEBAR.PCC-Palette -> sattes Rot mit dunkler Umrandung, gleiche Farbe wie der Doppelpunkt. Herzen: 6 Stueck im 3x2-Grid (Original-Screenshot), Start/Reset auf 6. Co-Authored-By: Claude Fable 5 --- NOTES.md | 18 ++++++++++++ game/level.py | 76 ++++++++++++++++++++++----------------------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/NOTES.md b/NOTES.md index e48a67f..3b0d792 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1535,3 +1535,21 @@ Smacks unter der Bruecke stoesst korrekt an die Decke) + E2E rc=0 + --once ok. Verifiziert: Slope-Drop pixelgenau, Plateau-Aufstieg + Weiterlauf, Wand- Integritaet, Smacks idle=12, --once exit 0, E2E rc=0. + +## 25.07.2026 (6) -- HUD final: GAMEBAR pur (weisse Boxen) + Original-Ziffern + +Stefans Korrektur zur letzten Runde: die Box-Innenflaechen sind im Original +WEISS (genau wie in der GAMEBAR.PCC-Grafik -- die dunkelroten Boxen im +frueheren DOSBox-Screenshot waren wohl ein Farb-Artefakt), die Zahlen sind +ROT in der Original-HUD-Font, und es sind 6 HERZEN (3x2). + +Loesung: GAMEBAR.PCC wird jetzt PUR geblittet (keine Fuellung mehr, der +Grafik-":" ist auf weiss natuerlich sichtbar). Die Zahlen sind die +GAMEBAR.BOB-Ziffern (7x13) gerendert mit der GAMEBAR.PCC-PALETTE -- damit +sind sie sattrot mit dunkler Umrandung, exakt wie der ":" (mit der +bob-Regel-Palette waren sie braeunlich; Stefan: "koennte sogar braun sein" +-- die PCC-Palette ist die konsistente Wahl, Umschalten waere 1 Zeile). +Herzen: 6 (3x2-Grid, Frame 10 mit PCC-Palette), leere Plaetze bleiben weiss. +hearts-Start/-Reset = 6. + +HUD-Render deckungsgleich mit Stefans Original-Screenshot. --once/E2E ok. diff --git a/game/level.py b/game/level.py index 6a52041..5f1a171 100644 --- a/game/level.py +++ b/game/level.py @@ -423,34 +423,20 @@ class Hud: [57-99 Icon+Kekse][105-154 Item][160-210 Score][216-248 Herzen 2x2] [254-280 Kopf+Leben][286-315 Uhr].''' - BOX_FILL = (146, 10, 10) - def __init__(self, assets): - from .menu import BitmapFont, _mapping_from_rows + from .formats import load_pcc container = assets.container + # Die Boxen der GAMEBAR.PCC bleiben WEISS (die Grafik hat das schon + # richtig -- Stefans Korrektur); Ziffern/Herzen kommen aus + # GAMEBAR.BOB, gerendert mit der GAMEBAR.PCC-PALETTE (damit sind die + # Ziffern ROT mit dunkler Umrandung wie im Original -- mit der + # bob-Regel-Palette waren sie braun). + _, _, _, gb_pal = load_pcc(container.entries['GAMEBAR.PCC']) frames = parse_bob(container.entries['GAMEBAR.BOB']) - palette = get_bob_palette(container.entries, 'GAMEBAR') - self.icons = _frames_to_surfaces(frames, palette) + self.icons = _frames_to_surfaces(frames, gb_pal) + self.digits = self.icons[0:10] # 7x13, rot self.heart_full = self.icons[10] - self.font = BitmapFont(assets.pcc_surface('FON_1B'), 9, 7, - _mapping_from_rows(['1234567890;:!"%/()=?,.-\x7f#']), - spacing=8) - # GAMEBAR.PCC vorbereiten: Innenflaechen der 6 Boxen dunkelrot, - # der Grafik-":" (Uhr-Box) gelb wie die Ziffern. - bar = assets.pcc_surface('GAMEBAR').convert() - import pygame.surfarray as sa - arr = sa.pixels3d(bar) - w = arr.shape[0] - for x in range(56, w): - col = arr[x] - for y in range(col.shape[0]): - r, g, b = col[y] - if r > 200 and g > 200 and b > 200: - col[y] = self.BOX_FILL - elif 292 <= x <= 302 and r > 150 and g < 100: - col[y] = (255, 222, 0) # ":"-Punkte der Uhr - del arr - self.bar = bar + self.bar = assets.pcc_surface('GAMEBAR').convert() self.item_icons = {n: intro.make_border_bg_transparent(assets.pcc_surface(n)) for n in ('ITE0', 'ITE1', 'ITE2', 'ITE3')} self.heads_small = [] @@ -458,32 +444,34 @@ class Hud: head = intro.make_border_bg_transparent(assets.pcc_surface(f'WECH_{i}')) self.heads_small.append(pygame.transform.smoothscale(head, (17, 16))) - def _text(self, canvas, x, y, text): - canvas.blit(self.font.render(text, outline=(0, 0, 0)), (x, y)) + def _number(self, canvas, x, y, value, width): + s = str(max(0, int(value))).rjust(width, '0')[-width:] + for i, ch in enumerate(s): + canvas.blit(self.digits[int(ch)], (x + i * 8, y)) def draw(self, canvas, y0, char_def, cookies, score, hearts, lives, time_left): canvas.blit(self.bar, (0, y0)) - text_y = y0 + 9 - # Box 1: Cerealien-Icon des aktiven Charakters + Keks-Zaehler + num_y = y0 + 6 + # Box 1 (57-99): Cerealien-Icon des aktiven Charakters + Keks-Zaehler icon = self.item_icons.get(char_def['item_icon']) if icon: - canvas.blit(icon, (59, y0 + 4)) - self._text(canvas, 76, text_y, f'{cookies:03d}') + canvas.blit(icon, (58, y0 + 4)) + self._number(canvas, 75, num_y, cookies, 3) # Box 2 (105-154): Item -- noch leer - # Box 3: Score - self._text(canvas, 161, text_y, f'{score:06d}') - # Box 4: Herzen 2x2 (leere Plaetze bleiben dunkel) - for i in range(min(hearts, 4)): - canvas.blit(self.heart_full, (221 + (i % 2) * 11, y0 + 4 + (i // 2) * 9)) - # Box 5: Charakter-Kopf (immer die gewaehlte Figur) + Leben + # Box 3 (160-210): Score + self._number(canvas, 161, num_y, score, 6) + # Box 4 (216-248): Herzen, 3x2-Grid, max 6 (Original-Screenshot); + # leere Plaetze bleiben weiss + for i in range(min(hearts, 6)): + canvas.blit(self.heart_full, (218 + (i % 3) * 10, y0 + 4 + (i // 3) * 9)) + # Box 5 (254-280): Charakter-Kopf (immer die gewaehlte Figur) + Leben canvas.blit(self.heads_small[char_def['head_index']], (254, y0 + 4)) - self._text(canvas, 272, text_y, str(lives)) - # Box 6: Uhr (der Grafik-":" ist rot auf dunkelrot kaum sichtbar -- - # eigener gelber ":" per Font drueber) + self._number(canvas, 272, num_y, lives, 1) + # Box 6 (286-315): Uhr -- der ":" ist Teil der Grafik (auf weiss + # sichtbar, Stefans Bestaetigung) m, s = divmod(max(0, int(time_left)), 60) - self._text(canvas, 288, text_y, str(m)) - self._text(canvas, 294, text_y, ':') - self._text(canvas, 301, text_y, f'{s:02d}') + self._number(canvas, 288, num_y, m, 1) + self._number(canvas, 300, num_y, s, 2) def run_character_select(clock, assets, available, current): @@ -560,7 +548,7 @@ def run_level(clock, assets, audio_paths, map_name='W1L1'): start = time.monotonic() map_w_px = level.width * TILE map_h_px = level.height * TILE - hearts, lives = 4, 3 + hearts, lives = 6, 3 # 6 Herzen (3x2) -- Original-Screenshot water_t = 0.0 while True: @@ -597,7 +585,7 @@ def run_level(clock, assets, audio_paths, map_name='W1L1'): hearts -= 1 if hearts <= 0: lives -= 1 - hearts = 4 + hearts = 6 player.x, player.y = spawn_px player.vy = 0.0 if lives <= 0: