Levelende v1: Exit-Zone -> Zusammenfassungstafel (Original-Layout) -> Kartenfortschritt; TIME-OUT/Levelende-Tafeln bleiben bis Enter/Space stehen
This commit is contained in:
@@ -2089,3 +2089,23 @@ die "Absprung-Hocke" komplett entfernt (Sprung ist jetzt nur 8 hoch /
|
||||
(Slot 10). Slot 17 (frontal) ist damit nirgends mehr in Gebrauch;
|
||||
die sess_level-"Frontal am Levelstart"-Deutung aus Eintrag (26) war
|
||||
wohl eine Fehlinterpretation der kleinen Crops.
|
||||
|
||||
## 26.07.2026 (35) -- Levelende v1 + Tafeln bleiben stehen
|
||||
|
||||
Stefans Regeln: TIME-OUT-Tafel (und Levelende-Tafel) bleiben STEHEN bis
|
||||
Enter/Leertaste (_wait_panel). NEU Levelende v1:
|
||||
- Exit-Zone erreicht -> Zusammenfassungstafel (SCORE/MAXIMUM/GESAMMELT/
|
||||
VITAMINE/"0 X" -- nach Stefans Original-Screenshot; Werte noch 0, bis
|
||||
Items gebaut sind; MAXIMUM = echte ARE-Zaehlung 151+154) -> 'completed'
|
||||
-> intro.py laesst die Kartenfigur zum naechsten Punkt weiterwandern
|
||||
(Punkt + Spur werden blau, Original-Regeln aus (31)/(33)).
|
||||
- Exit-Zone W1L1 = SCHAETZUNG (rechtes Ende, um ARE-Objekt 194 bei
|
||||
(3168,432)): exit_px=(3140,300,348,452). Echte Stelle + Aussehen des
|
||||
Ausgangs von Stefan/DOSBox zu verifizieren!
|
||||
- MAXIMUM-Diskrepanz: wir zaehlen 137 (151er+154er), Stefans Original-
|
||||
Screen zeigte 158 -- vermutlich zaehlen ?-Box-Inhalte (71-76) und/oder
|
||||
15x-Typen mit. Offen.
|
||||
- ctype-Nibble-12 (44) liegt NICHT am Levelende (2 Tiles bei (91/99,17))
|
||||
-- also kein Exit-Marker; Bedeutung offen. Bit 8 steckt zudem in
|
||||
Standard-Boden (40=32+8) => Coco-Ast-Trigger (Bit 8) ist FALSCH und
|
||||
muss neu bestimmt werden (aktuell greift Coco evtl. am Boden?? pruefen).
|
||||
|
||||
+9
-1
@@ -990,7 +990,15 @@ def main():
|
||||
elif state == 'level':
|
||||
r = level_mod.run_level(clock, assets, audio_paths,
|
||||
map_name=pending_map)
|
||||
if r == 'map':
|
||||
if r == 'completed':
|
||||
# Level geschafft: Kartenfigur laeuft zum
|
||||
# naechsten Punkt weiter (Punkt/Spur werden blau)
|
||||
wm = map_state.get('wm')
|
||||
if wm is not None and wm.current < len(wm.segments) - 1:
|
||||
wm.current += 1
|
||||
play_title_music()
|
||||
state = 'map'
|
||||
elif r == 'map':
|
||||
play_title_music() # Karte/Menue laufen mit Titelmusik
|
||||
state = 'map'
|
||||
else:
|
||||
|
||||
+82
-10
@@ -144,6 +144,10 @@ LEVEL_INFO = {
|
||||
chars=['TONY', 'SMACKS'], # Level 1: nur die beiden (Stefan)
|
||||
water_y=42 * TILE, # Wasseroberflaeche unter der Bruecke
|
||||
door_px=(12 * TILE, 37 * TILE, 2 * TILE, 3 * TILE), # Haus-Tuer (x,y,w,h)
|
||||
# Levelende-Zone (v1-SCHAETZUNG: rechtes Levelende um das letzte
|
||||
# ARE-Objekt Typ 194 bei (3168,432) -- echte Stelle noch per
|
||||
# Stefan/DOSBox zu verifizieren)
|
||||
exit_px=(3140, 300, 348, 452),
|
||||
),
|
||||
}
|
||||
WATER_TINT = (10, 20, 120, 110) # dunkelblaues Overlay
|
||||
@@ -741,6 +745,65 @@ def run_character_select(clock, assets, available, current):
|
||||
clock.tick(30)
|
||||
|
||||
|
||||
def _wait_panel(clock, panel):
|
||||
'''Tafel anzeigen, bis Enter/Leertaste gedrueckt wird (Stefans Regel
|
||||
fuer TIME-OUT- und Levelende-Tafel). Rueckgabe: 'ok' | 'quit'.'''
|
||||
pygame.event.clear()
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
return 'quit'
|
||||
if event.type == pygame.KEYDOWN and event.key in (
|
||||
pygame.K_RETURN, pygame.K_SPACE):
|
||||
return 'ok'
|
||||
intro._blit_centered(intro.build_letterboxed(panel))
|
||||
pygame.display.flip()
|
||||
clock.tick(30)
|
||||
|
||||
|
||||
def _parse_are_objects(are_bytes, map_w_tiles, map_h_tiles):
|
||||
'''Objektliste (x_px, y_px, typ) aus einer .ARE (Format: NOTES (24)).'''
|
||||
import struct
|
||||
d = are_bytes
|
||||
sec_w = (map_w_tiles * 16 + 63) // 64
|
||||
sec_h = (map_h_tiles * 16 + 63) // 64
|
||||
objs = []
|
||||
for sy in range(sec_h):
|
||||
for sx in range(sec_w):
|
||||
off = struct.unpack('>H', d[352 + (sy * sec_w + sx) * 2:
|
||||
354 + (sy * sec_w + sx) * 2])[0]
|
||||
if off == 0xffff:
|
||||
continue
|
||||
q = 352 + off
|
||||
while q < len(d) - 1:
|
||||
v = struct.unpack('>H', d[q:q + 2])[0]
|
||||
if v == 0xffff:
|
||||
if q == 352 + off:
|
||||
q += 2
|
||||
continue
|
||||
break
|
||||
typ, dx, dy = struct.unpack('>3H', d[q:q + 6])
|
||||
objs.append((sx * 64 + dx, sy * 64 + dy, typ))
|
||||
q += 6
|
||||
return objs
|
||||
|
||||
|
||||
def _summary_panel(assets, collected, maximum, vitamins, score):
|
||||
'''Levelende-Tafel nach Stefans Original-Screenshot: SCORE, MAXIMUM/
|
||||
GESAMMELT (Cerealien), VITAMINE, Bonusleben-Zeile.'''
|
||||
from .menu import MenuAssets
|
||||
m = MenuAssets(assets)
|
||||
panel = m.menu_bg.copy()
|
||||
def line(text, y):
|
||||
surf = m.font_big.render(text)
|
||||
panel.blit(surf, ((320 - surf.get_width()) // 2, y))
|
||||
line(f'SCORE: {score}', 48)
|
||||
line(f'MAXIMUM {maximum} GESAMMELT {collected}', 66)
|
||||
line(f'VITAMINE {vitamins}', 84)
|
||||
line('0 X', 116)
|
||||
return panel
|
||||
|
||||
|
||||
def run_level(clock, assets, audio_paths, map_name='W1L1'):
|
||||
'''Level spielen. ESC -> 'map', Fenster-X -> 'quit'.'''
|
||||
level = Level(assets, map_name)
|
||||
@@ -808,6 +871,23 @@ def run_level(clock, assets, audio_paths, map_name='W1L1'):
|
||||
vx=55.0 * player.facing, t=0.0))
|
||||
|
||||
keys = pygame.key.get_pressed()
|
||||
# Levelende erreicht? -> Zusammenfassungstafel, dann Karte (Punkt
|
||||
# wird blau, Figur wandert weiter -- intro.py behandelt 'completed')
|
||||
exit_zone = info.get('exit_px')
|
||||
if (dying is None and exit_zone
|
||||
and pygame.Rect(exit_zone).collidepoint(player.x, player.y - 8)):
|
||||
w, h = level.width, level.height
|
||||
try:
|
||||
objs = _parse_are_objects(
|
||||
assets.container.entries[map_name + '.ARE'], w, h)
|
||||
maximum = sum(1 for _, _, t in objs if t in (151, 154))
|
||||
except Exception:
|
||||
maximum = 0
|
||||
panel = _summary_panel(assets, collected=0, maximum=maximum,
|
||||
vitamins=0, score=0)
|
||||
if _wait_panel(clock, panel) == 'quit':
|
||||
return 'quit'
|
||||
return 'completed'
|
||||
time_left = info['time'] - (time.monotonic() - start)
|
||||
# Zeit abgelaufen -> TIME-OUT-Tafel (Original-Screen, Stefans
|
||||
# Screenshot: Menue-Rahmen + "TIME OUT"), dann Leben -1 und Respawn
|
||||
@@ -817,16 +897,8 @@ def run_level(clock, assets, audio_paths, map_name='W1L1'):
|
||||
panel = m.menu_bg.copy()
|
||||
txt = m.font_big.render('TIME OUT')
|
||||
panel.blit(txt, ((320 - txt.get_width()) // 2, 72))
|
||||
end = time.monotonic() + 2.5
|
||||
while time.monotonic() < end:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
return 'quit'
|
||||
if event.type == pygame.KEYDOWN:
|
||||
end = 0
|
||||
intro._blit_centered(intro.build_letterboxed(panel))
|
||||
pygame.display.flip()
|
||||
clock.tick(30)
|
||||
if _wait_panel(clock, panel) == 'quit':
|
||||
return 'quit'
|
||||
lives -= 1
|
||||
if lives <= 0:
|
||||
return 'map'
|
||||
|
||||
Reference in New Issue
Block a user