Titelbild in voller Aufloesung (320x480 anamorph statt halbiert)

Stefan-Frage "hatte das Titelbild nicht bessere Aufloesung?" -- ja, bestaetigt.
Die 4 Quadranten KELL256A-D (je 160x240 nativ) wurden bisher auf halbe Hoehe
(160x120) gestaucht -> 320x240, also die halbe vertikale Aufloesung verworfen
(gleiche Fehlklasse wie der Rauser-0.5x-Downscale). Ein RMSE-Vergleich der
beiden Varianten gegen die echte DOSBox-Referenzaufnahme belegt eindeutig die
volle Variante:
  voll (320x480, anamorph angezeigt): RMSE 0.014
  halbiert (320x240):                 RMSE 0.083  (6x schlechter)

Fix: build_title_quadrants nutzt die nativen 160x240-Quadranten -> 320x480-
Bild; angezeigt wird es anamorph auf die volle Fenstergroesse gestreckt
(_blit_title: 320x480 -> 960x720, x3 Breite / x1.5 Hoehe), womit alle 480
Zeilen erhalten bleiben. render_title_wipe_frame arbeitet automatisch bei
320x480 (Hoehe aus get_height()). pcc_surface_half_height entfernt (ungenutzt).

Verifiziert: neues Titelbild sichtbar schaerfer, deckungsgleich zur Referenz;
python -m game --once (headless) exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck
2026-07-24 01:59:19 +02:00
co-authored by Claude Opus 4.8
parent 95e5b1edb4
commit ccad606a43
+40 -41
View File
@@ -66,20 +66,17 @@ Serie vermessen, siehe NOTES.md Abschnitt "Boot-Sequenz vermessen". Kurzfassung:
6. kurze schwarze Pause
7. Titelbild "TONY & FRIENDS in Kellogg's Land" -- die 4 Quadranten KELL256A
(oben links) / B (oben rechts) / C (unten links) / D (unten rechts) sind
je 160x240 PCC-Nativaufloesung, werden aber nur bei **halber Groesse**
(160x120) in ein 2x2-Raster gezeichnet: A|B oben, C|D unten -> 320x240
Gesamtbild. Per Pixel-Rekonstruktion gegen eine echte DOSBox-Aufnahme
verifiziert. Reveal-Effekt: obere Haelfte (A|B) waechst von oben (Hoehe
0->120), untere Haelfte (C|D) waechst von unten (Hoehe 0->120) -- treffen
sich in der Mitte. Waehrend dieser Reveal-Phase ist die untere Haelfte
erst graustichig/entsaettigt MIT Scanlines ueberzogen, die sich danach in
einer zweiten Phase zu vollen Farben aufloesen (Stefans "Screenshot
4/5/6"-Effekt). HINWEIS: diese Quadranten nutzen denselben
Downscale-Mechanismus (smoothscale halbe Hoehe) wie die Rauser-Assets
vor dem obigen Fix -- hier bisher KEINE Bildschaerfe-Beschwerde von
Stefan, deshalb unangetastet gelassen. Falls das Titelbild auch mal als
"verwaschen" gemeldet wird: gleicher Fix-Ansatz (native Groesse zeichnen,
nur einmal ganzzahlig hochskalieren) anwendbar.
je 160x240 PCC-Nativaufloesung und werden in NATIVER Groesse in ein
2x2-Raster gezeichnet: A|B oben, C|D unten -> 320x480 Gesamtbild. Das wird
beim Anzeigen ANAMORPH auf 4:3 (Fenstergroesse) gestreckt -- doppelt hohe
Pixel, genau wie im Original (siehe _blit_title). KORREKTUR 24.07.2026:
frueher wurden die Quadranten auf halbe Hoehe gestaucht (320x240) -- das
war falsch (halbe vertikale Aufloesung). RMSE-Vergleich gegen die echte
DOSBox-Referenz: 0.014 (voll) vs. 0.083 (halbiert). Reveal-Effekt: obere
Haelfte (A|B) waechst von oben, untere (C|D) von unten, treffen sich in
der Mitte (y=240). Waehrend/nach dem Reveal ist die untere Haelfte mit
Scanlines ueberzogen (KEIN Grau mehr), die sich von der Mitte nach unten
aufloesen.
Alle Nicht-BOB/ICO/MAP-Assets werden per kellogg_formats.load_pcc() (Pillows
PCX-Decoder) aus PCKELL.DAT gelesen -- kein eigener RLE-Code mehr (siehe
@@ -220,6 +217,17 @@ def _blit_centered(surface):
keinen veralteten Screen-Bezug hinterlaesst).'''
blit_scaled_centered(pygame.display.get_surface(), surface, WINDOW_W, WINDOW_H)
def _blit_title(surface):
'''Titelbild-Sonderfall: die Quelle ist 320x480 (ein 4:3-Bild mit doppelt
hohen Pixeln -- genau so liegt es im Original vor, siehe Titelbild-
Aufloesungs-Fund 24.07.2026). Es wird ANAMORPH auf die volle Fenstergroesse
gestreckt (320x480 -> 960x720, also x3 Breite / x1.5 Hoehe) -- fuellt das
Fenster wie die 320x240-Screens, behaelt aber die volle vertikale
Aufloesung (480 statt der frueher faelschlich halbierten 240 Zeilen).'''
s = pygame.display.get_surface()
s.blit(pygame.transform.scale(surface, (WINDOW_W, WINDOW_H)), (0, 0))
# "praesentiert"-Text-Faelle in KELLOGGS.PCC (siehe Docstring)
PRAESENTIERT_FADE_INDICES = [34, 42, 43, 44, 45]
PRAESENTIERT_FADE_SECONDS = 2.5
@@ -389,20 +397,6 @@ class Assets:
new_size = (max(1, round(w * scale)), max(1, round(h * scale)))
return pygame.transform.scale(surf, new_size)
def pcc_surface_half_height(self, name):
'''Skaliert NUR die Hoehe um 0.5, Breite bleibt nativ -- fuer die
Titelbild-Quadranten KELL256A/B/C/D (160x240 -> 160x120). ACHTUNG:
das ist KEINE gleichmaessige Skalierung wie bei den Rauser-Assets --
per Pixel-Rekonstruktion gegen eine echte DOSBox-Aufnahme verifiziert
(siehe Docstring ganz oben). Nearest-Neighbor (pygame.transform.scale)
statt smoothscale aus dem gleichen Grund wie bei den Rauser-Assets
(siehe pcc_surface_scaled) -- konsistent scharf.'''
surf = self.pcc_surface(name)
w, h = surf.get_size()
new_size = (w, max(1, round(h * 0.5)))
return pygame.transform.scale(surf, new_size)
def fit_scale(src_w, src_h, max_w, max_h):
return min(max_w / src_w, max_h / src_h)
@@ -720,20 +714,25 @@ def scene_rauser(clock, assets, audio_paths):
# ---------------------------------------------------------------------------
def build_title_quadrants(assets):
'''Liefert die 4 Titelbild-Quadranten bei halber Hoehe (160x120 statt
160x240 nativ) -- A/B oben, C/D unten. Per Pixel-Rekonstruktion gegen
eine echte DOSBox-Aufnahme verifiziert.'''
'''Liefert die 4 Titelbild-Quadranten in NATIVER Aufloesung (je 160x240)
-- A/B oben, C/D unten -> zusammen ein 320x480-Bild. KORREKTUR 24.07.2026:
frueher wurden die Quadranten auf halbe Hoehe (160x120) gestaucht; ein
Vergleich gegen die echte DOSBox-Referenz (RMSE 0.014 voll vs. 0.083
halbiert) zeigt aber, dass das Original das Bild in voller Hoehe fuehrt und
nur ANAMORPH (doppelt hohe Pixel) auf 4:3 anzeigt. Die native Hoehe bleibt
also erhalten und wird erst beim Anzeigen gestreckt (siehe _blit_title).'''
return {
'A': assets.pcc_surface_half_height('KELL256A'),
'B': assets.pcc_surface_half_height('KELL256B'),
'C': assets.pcc_surface_half_height('KELL256C'),
'D': assets.pcc_surface_half_height('KELL256D'),
'A': assets.pcc_surface('KELL256A'),
'B': assets.pcc_surface('KELL256B'),
'C': assets.pcc_surface('KELL256C'),
'D': assets.pcc_surface('KELL256D'),
}
def build_title_image(quads):
'''Komplettes, ruhendes Titelbild (320x240) aus den 4 halbskalierten
Quadranten im 2x2-Raster.'''
'''Komplettes, ruhendes Titelbild (320x480) aus den 4 nativen Quadranten im
2x2-Raster (wird beim Anzeigen anamorph auf 4:3 gestreckt, siehe
_blit_title).'''
a, b, c, d = quads['A'], quads['B'], quads['C'], quads['D']
w = a.get_width() + b.get_width()
h = a.get_height() + c.get_height()
@@ -775,10 +774,10 @@ def render_title_wipe_frame(quads, t):
unteren Haelfte loesen sich von der Mitte nach unten auf. Obere Haelfte ist
durchgehend volle Farbe ohne Scanlines (wie in der DOSBox-Referenz).'''
a, b, c, d = quads['A'], quads['B'], quads['C'], quads['D']
half_h = a.get_height() # 120
half_h = a.get_height() # 240 (native Quadrantenhoehe)
full_w = a.get_width() + b.get_width() # 320
canvas = pygame.Surface((full_w, half_h * 2))
canvas = pygame.Surface((full_w, half_h * 2)) # 320x480
canvas.fill((0, 0, 0))
if t < TITLE_HEIGHT_REVEAL_FRACTION:
@@ -866,12 +865,12 @@ def scene_title(clock, assets, hold_forever=True):
kurz und kehrt zurueck, statt auf eine Taste zu warten.'''
quads = build_title_quadrants(assets)
r = wait_or_skip(clock, TITLE_WIPE_SECONDS,
lambda t: _blit_centered(render_title_wipe_frame(quads, t)))
lambda t: _blit_title(render_title_wipe_frame(quads, t)))
if r == 'quit':
return 'quit'
# 'skip' waehrend der Wipe-Animation -> direkt zum fertigen Titelbild
title_img = build_title_image(quads)
draw = lambda _t: _blit_centered(title_img)
draw = lambda _t: _blit_title(title_img)
if hold_forever:
return wait_for_key(clock, draw)
return wait_or_skip(clock, 3.0, draw)