Weltkarte pixelexakt: gemessene Blit-Anker (Basis=(x,218-y)), Punkt steht + Kopf blinkt darueber, Segment/Name-Zuordnung um 1 korrigiert (W1L0 hat keinen Kartenpunkt)
This commit is contained in:
@@ -1739,3 +1739,41 @@ Binary-KOORDINATEN stimmen, aber der BLIT-ANKER des Originals (topleft vs
|
|||||||
zentriert) steht nicht im Binary -- wir hatten zentriert geraten. Fix:
|
zentriert) steht nicht im Binary -- wir hatten zentriert geraten. Fix:
|
||||||
empirische Offsets MAP_DX=5/MAP_DY=4 in worldmap._tf() (dort feinjustieren,
|
empirische Offsets MAP_DX=5/MAP_DY=4 in worldmap._tf() (dort feinjustieren,
|
||||||
falls noch nicht exakt).
|
falls noch nicht exakt).
|
||||||
|
|
||||||
|
## 26.07.2026 (16) -- Karte PIXELEXAKT: Template-Matching statt Schaetzung
|
||||||
|
|
||||||
|
Stefans Nachmessung: immer noch daneben ("noch ein bisschen nach rechts
|
||||||
|
und weiter runter"). Diesmal richtig gemessen: KARTE-Sprites per
|
||||||
|
Template-Matching (mit Alpha-Maske) in den DOSBox-Referenzframes gesucht.
|
||||||
|
Ergebnis eindeutig (err ~10 = VGA-DAC-Rauschen, naechster Kandidat >200):
|
||||||
|
|
||||||
|
- KARTE0 (10x7) steht DAUERHAFT, Topleft (58,162) -- in BEIDEN Blinkphasen!
|
||||||
|
- KARTE4-Kopf (14x15) blinkt DARUEBER an/aus, Topleft (53,146) (steht auf
|
||||||
|
dem Punkt). Frueherer Befund "Punkt und Kopf wechseln sich ab" war
|
||||||
|
falsch (Diff-Region war die VEREINIGUNG beider Sprites).
|
||||||
|
- KARTE3 (kleine Punkte): am Spielstart NIRGENDS auf der Karte -- nicht
|
||||||
|
freigeschaltete Level sind unsichtbar (bestaetigt die Netz-Screenshots:
|
||||||
|
dort ist das Spiel durchgespielt).
|
||||||
|
|
||||||
|
Daraus die exakten Anker (Binary-Label (x,y)): Basis = (x, 218-y);
|
||||||
|
KARTE0-Topleft = Basis+(5,0); Kopf-Topleft = Basis+(0,-16); KARTE3
|
||||||
|
zentriert auf dem grossen Punkt = Basis+(7,2) (einzige verbleibende
|
||||||
|
Annahme -- kleine Punkte gibt es in keiner DOS-Referenzaufnahme).
|
||||||
|
|
||||||
|
WICHTIGER NEBENFUND -- Segment/Namens-Zuordnung war um 1 verschoben:
|
||||||
|
Das Start-Label (53,56) gehoert zu SEGMENT 0, und 21 Segmente = exakt
|
||||||
|
die 21 anwaehlbaren Level W1L1..W3L7 (3 Welten x 7). W1L0 (22. Name,
|
||||||
|
MAP existiert) hat KEINEN Kartenpunkt (Bonus-/Geheimlevel?). Also
|
||||||
|
segments[i] = names[i+1]; der "fehlende W3L7-Randfall" aus Eintrag (13)
|
||||||
|
war keiner. Cursorstart = Segment 0 = W1L1.
|
||||||
|
|
||||||
|
Disassembly-Check (Stefans Frage "bekommst du das nicht aus dem
|
||||||
|
Disassembler?"): einziges `mov ax,218` im Binary (Offset 0xf084) ist
|
||||||
|
eine HUD-ZIFFERN-Routine (X-Positionen 186/194/202, Spriteindex =
|
||||||
|
Ziffer+500 -- notiert fuer die Punkteanzeige!). Der Karten-Anker steht
|
||||||
|
nicht als Literal im Code -> Pixelmessung war der richtige Weg.
|
||||||
|
|
||||||
|
Verifikation: eigener Karten-Render vs. DOSBox-Frame, mittlerer
|
||||||
|
Pixelfehler 5.0 (identisch mit dem Ganzbild-Grundrauschen der
|
||||||
|
VGA-DAC-Quantisierung) in beiden Blinkphasen => pixelidentisch.
|
||||||
|
--once exit 0.
|
||||||
|
|||||||
+27
-27
@@ -28,21 +28,22 @@ from . import intro
|
|||||||
HEAD_SPRITE = {'TONY': 'KARTE4', 'SMACKS': 'KARTE5', 'TOUCAN': 'KARTE6', 'COCO': 'KARTE7'}
|
HEAD_SPRITE = {'TONY': 'KARTE4', 'SMACKS': 'KARTE5', 'TOUCAN': 'KARTE6', 'COCO': 'KARTE7'}
|
||||||
STEP_SECONDS = 0.18 # Lauftempo der Kartenfigur pro Wegpunkt
|
STEP_SECONDS = 0.18 # Lauftempo der Kartenfigur pro Wegpunkt
|
||||||
BLINK_SECONDS = 0.5 # Blinkrhythmus der aktiven Position
|
BLINK_SECONDS = 0.5 # Blinkrhythmus der aktiven Position
|
||||||
# Die Binary-Koordinaten sind y-GEFLIPPT (DOSBox-Nachmessung 25.07.2026:
|
# Die Binary-Koordinaten sind y-GEFLIPPT. Pixelexakte DOSBox-Nachmessung
|
||||||
# Level-1-Punkt real bei (59,153), Binary-Label (53,56) -> screen_y = 209-y;
|
# (Template-Matching der KARTE-Sprites, 26.07.2026): Binary-Label von W1L1
|
||||||
# damit liegen die fruehen Level im Wald unten und W2/W3 in Bergen/Schloss
|
# ist (53,56); im Original steht KARTE0 (10x7) mit Topleft bei (58,162) und
|
||||||
# oben -- deckungsgleich mit Stefans Original-Screenshots).
|
# der Mini-Kopf KARTE4 (14x15) blinkt DARUEBER bei Topleft (53,146) --
|
||||||
MAP_Y_FLIP = 209
|
# der Punkt bleibt also dauerhaft stehen, nur der Kopf geht an/aus.
|
||||||
# Blit-Anker-Korrektur (Stefans Abgleich mit Original-Screenshots: "alle
|
# Daraus: Basis = (x_bin, 218 - y_bin), Punkt-Topleft = Basis+(5,0),
|
||||||
# Punkte ein Stueck nach rechts und unten"): die Binary-Koordinaten sind
|
# Kopf-Topleft = Basis+(0,-16). Die Anker stehen nicht als Literal im
|
||||||
# korrekt, aber das Original ankert die Sprites nicht zentriert -- der
|
# Binary (Code rechnet sie indirekt), daher per Messung fixiert.
|
||||||
# Versatz ist im Binary nicht ablesbar, daher empirisch. Feinjustage hier.
|
MAP_Y_FLIP = 218
|
||||||
MAP_DX = 5
|
DOT_OFF = (5, 0) # KARTE0/KARTE2 (10x7), Topleft relativ zur Basis
|
||||||
MAP_DY = 4
|
HEAD_OFF = (0, -16) # KARTE4-7 (14x15), steht auf dem Punkt
|
||||||
|
SMALL_OFF = (7, 2) # KARTE3 (6x4), zentriert auf dem grossen Punkt
|
||||||
|
|
||||||
|
|
||||||
def _tf(p):
|
def _tf(p):
|
||||||
return (p[0] + MAP_DX, MAP_Y_FLIP - p[1] + MAP_DY)
|
return (p[0], MAP_Y_FLIP - p[1])
|
||||||
|
|
||||||
|
|
||||||
def parse_worldmap(exe_path):
|
def parse_worldmap(exe_path):
|
||||||
@@ -123,8 +124,11 @@ class WorldMap:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(f'[worldmap] Binary-Pfaddaten nicht lesbar ({exc}) -- '
|
print(f'[worldmap] Binary-Pfaddaten nicht lesbar ({exc}) -- '
|
||||||
f'Fallback nur Level 1', file=sys.stderr)
|
f'Fallback nur Level 1', file=sys.stderr)
|
||||||
self.segments = [dict(waypoints=[(113, 35)], stand=(113, 35), label=(108, 51))]
|
self.segments = [dict(waypoints=[(53, 56)], stand=(53, 56), label=(53, 56))]
|
||||||
self.names = ['W1L1']
|
self.names = ['W1L0', 'W1L1']
|
||||||
|
# 21 Segmente fuer 21 anwaehlbare Level (W1L1..W3L7, 3 Welten x 7);
|
||||||
|
# W1L0 (Name Nr. 0) hat KEINEN Kartenpunkt -> segments[i] = names[i+1].
|
||||||
|
self.level_names = self.names[1:]
|
||||||
# Positionen ins Screen-System transformieren (y-Flip)
|
# Positionen ins Screen-System transformieren (y-Flip)
|
||||||
for seg in self.segments:
|
for seg in self.segments:
|
||||||
seg['waypoints'] = [_tf(p) for p in seg['waypoints']]
|
seg['waypoints'] = [_tf(p) for p in seg['waypoints']]
|
||||||
@@ -137,7 +141,7 @@ class WorldMap:
|
|||||||
self.dot_small = intro.make_border_bg_transparent(assets.pcc_surface('KARTE3'))
|
self.dot_small = intro.make_border_bg_transparent(assets.pcc_surface('KARTE3'))
|
||||||
self.heads = {c: intro.make_border_bg_transparent(assets.pcc_surface(n))
|
self.heads = {c: intro.make_border_bg_transparent(assets.pcc_surface(n))
|
||||||
for c, n in HEAD_SPRITE.items()}
|
for c, n in HEAD_SPRITE.items()}
|
||||||
self.current = 1 if len(self.segments) > 1 else 0 # Start: Level 1 (Index 0 = W1L0)
|
self.current = 0 # Segment 0 = W1L1 (DOSBox-Messung: Startpunkt (53,56))
|
||||||
|
|
||||||
def draw(self, canvas, char, t, walk_pos=None):
|
def draw(self, canvas, char, t, walk_pos=None):
|
||||||
canvas.blit(self.karte, (0, 0))
|
canvas.blit(self.karte, (0, 0))
|
||||||
@@ -146,23 +150,19 @@ class WorldMap:
|
|||||||
for i, seg in enumerate(self.segments):
|
for i, seg in enumerate(self.segments):
|
||||||
if seg['label'] is None:
|
if seg['label'] is None:
|
||||||
continue
|
continue
|
||||||
lx, ly = seg['label']
|
bx, by = seg['label']
|
||||||
if i == self.current and walk_pos is None:
|
if i == self.current and walk_pos is None:
|
||||||
# Original-Verhalten (Netz-Referenzbilder + DOSBox-Diff):
|
# Original-Verhalten (DOSBox-Messung): der grosse Punkt
|
||||||
# an der aktuellen Position wechseln PUNKT und MINI-KOPF
|
# steht dauerhaft, der Mini-Kopf blinkt DARUEBER an/aus
|
||||||
|
canvas.blit(self.dot_big_on, (bx + DOT_OFF[0], by + DOT_OFF[1]))
|
||||||
if head_phase:
|
if head_phase:
|
||||||
canvas.blit(head, (lx - head.get_width() // 2, ly - head.get_height() // 2))
|
canvas.blit(head, (bx + HEAD_OFF[0], by + HEAD_OFF[1]))
|
||||||
else:
|
else:
|
||||||
canvas.blit(self.dot_big_on,
|
canvas.blit(self.dot_small, (bx + SMALL_OFF[0], by + SMALL_OFF[1]))
|
||||||
(lx - self.dot_big_on.get_width() // 2,
|
|
||||||
ly - self.dot_big_on.get_height() // 2))
|
|
||||||
else:
|
|
||||||
dot = self.dot_small
|
|
||||||
canvas.blit(dot, (lx - dot.get_width() // 2, ly - dot.get_height() // 2))
|
|
||||||
# waehrend des Laufens: Kopf entlang des Pfads
|
# waehrend des Laufens: Kopf entlang des Pfads
|
||||||
if walk_pos is not None:
|
if walk_pos is not None:
|
||||||
px, py = walk_pos
|
px, py = walk_pos
|
||||||
canvas.blit(head, (px - head.get_width() // 2, py - head.get_height()))
|
canvas.blit(head, (px + HEAD_OFF[0], py + HEAD_OFF[1]))
|
||||||
|
|
||||||
|
|
||||||
def run_worldmap(clock, assets, menu_assets, char='TONY', state={}):
|
def run_worldmap(clock, assets, menu_assets, char='TONY', state={}):
|
||||||
@@ -198,7 +198,7 @@ def run_worldmap(clock, assets, menu_assets, char='TONY', state={}):
|
|||||||
pts = list(reversed(wm.segments[wm.current]['waypoints']))
|
pts = list(reversed(wm.segments[wm.current]['waypoints']))
|
||||||
walking = {'pts': pts, 'i': 0.0, 'target': wm.current - 1}
|
walking = {'pts': pts, 'i': 0.0, 'target': wm.current - 1}
|
||||||
elif event.key in (pygame.K_SPACE, pygame.K_RETURN):
|
elif event.key in (pygame.K_SPACE, pygame.K_RETURN):
|
||||||
return ('level', wm.names[wm.current])
|
return ('level', wm.level_names[wm.current])
|
||||||
|
|
||||||
dt = clock.tick(60) / 1000.0
|
dt = clock.tick(60) / 1000.0
|
||||||
walk_pos = None
|
walk_pos = None
|
||||||
|
|||||||
Reference in New Issue
Block a user