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:
co-authored by
Claude Opus 4.8
parent
95e5b1edb4
commit
ccad606a43
+40
-41
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user