diff --git a/NOTES.md b/NOTES.md index 1fd9065..464fe84 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1607,3 +1607,17 @@ Tony-auf-Wasser+Frosties-Idle von Stefan als "sehr geil" abgenommen (kein Fix). 4. **Duck-Kamera-Flackern**: 0.2s-Grace-Period -- kurze Taste/on_ground- Blips (X11-Autorepeat sendet Release/Press-Paare) setzen den Halte-Timer nicht mehr zurueck. + +## 25.07.2026 (10) -- sechste Feedback-Runde: Wasser-Regeln + Peek-Frames + +- Ducken im Wasser fuer Nicht-Schwimmer verboten (Bounce + DOWN ergab + Duck-Pose auf der Oberflaeche). +- Wasser-Schaden: alle 1.5s statt 5s (Stefan: "5 Sekunden arg lang"). +- Schadens-Blinken nach Herzverlust (0.9s Sichtbarkeits-Toggle ~6Hz -- + ein eigenes Aua-Sprite gibt es in den BOBs nicht). Beim Todesstart wird + das Blinken deaktiviert (sonst waere die eingefrorene Blinkphase die + ganze Anim unsichtbar gewesen). +- TUER-REINSCHAU-Frames (Stefans Fund): TONY Frame 50 (Rueckenansicht!), + SMACKS Frame 48 -- jeweils der letzte Frame vor den Magenta- + Platzhaltern. Der als "gebueckt/kriechend" einsortierte Tony-50 war in + Wahrheit das Reinschauen. diff --git a/game/level.py b/game/level.py index d8b913a..de339e0 100644 --- a/game/level.py +++ b/game/level.py @@ -45,7 +45,7 @@ WALK_ANIM_FPS = 12.0 RUN_ANIM_FPS = 14.0 IDLE_ANIM_AFTER = 5.0 # Sekunden Stillstand bis zur Idle-Animation IDLE_ANIM_FPS = 2.5 -WATER_DAMAGE_EVERY = 5.0 # im Wasser: alle 5s ein Herz (Stefans Angabe) +WATER_DAMAGE_EVERY = 1.5 # im Wasser: alle 1.5s ein Herz (Stefan: 5s war arg lang) SPAWN_ANIM_SECONDS = 1.1 # Start-Sprite beim Levelstart/Charakterwechsel SPRITE_SINK = 4 # Fuesse sinken optisch in die Blaetter/Gras ein # (Stefans "Figuren schweben ein paar Pixel") @@ -74,7 +74,7 @@ CHAR_DEFS = { idle_anim_r=[44, 46, 48], idle_anim_l=[45, 47, 49], spawn_frame=22, # Arm nach oben gestreckt death_frame=38, drop_frame=40, # erschrocken; fallendes HALSTUCH - peek_frame=34, # in die offene Tuer schauen + peek_frame=50, # in die Tuer reinschauen (Rueckenansicht -- Stefans Fund) item_icon='ITE0', head_index=0, ), 'SMACKS': dict( @@ -89,7 +89,7 @@ CHAR_DEFS = { idle_anim_r=[31, 33, 35], idle_anim_l=[32, 34, 36], spawn_frame=22, # Daumen-hoch-Geste death_frame=26, drop_frame=29, # erschrocken; fallende KAPPE - peek_frame=20, + peek_frame=48, # Reinschau-Frame (letzter vor den Platzhaltern) item_icon='ITE1', head_index=1, ), 'COCO': dict( @@ -256,6 +256,7 @@ class Player: self.idle_t = 0.0 self.spawn_t = 0.0 # Start-Sprite-Sequenz (Arm hoch/Daumen hoch) self.force_frame = None # erzwungener Frame (Tuer-Peek, Tod) + self.hurt_t = 0.0 # Rest-Blinkzeit nach Schaden self._grounded_before = False self.set_character(char, pos) @@ -277,6 +278,8 @@ class Player: self.HITBOX_W, self.HITBOX_H) def update(self, level, dt, keys): + if self.hurt_t > 0: + self.hurt_t -= dt if self.spawn_t > 0: self.spawn_t -= dt # Eingabe bricht die Start-Pose sofort ab @@ -285,7 +288,10 @@ class Player: self.spawn_t = 0.0 in_water = level.in_water(self.y) self.swimming = in_water and self.d['can_swim'] - self.ducking = self.on_ground and not self.swimming and keys[pygame.K_DOWN] + # Ducken geht NICHT im Wasser (Stefans Regel -- auch nicht fuer + # Nicht-Schwimmer, die auf der Oberflaeche huepfen) + self.ducking = (self.on_ground and not self.swimming and not in_water + and keys[pygame.K_DOWN]) move = 0 if not self.ducking: if keys[pygame.K_LEFT]: @@ -437,6 +443,11 @@ class Player: return self._pick('idle_r', 'idle_l') def draw(self, screen, cam_x, cam_y): + # Schadens-Blinken: nach Herzverlust flackert die Figur kurz + # (klassisches Sichtbarkeits-Toggle -- ein eigenes "Aua"-Sprite gibt + # es in den BOBs nicht) + if self.hurt_t > 0 and int(self.hurt_t * 12) % 2 == 0: + return i = self.current_frame_index() surf = self.surfs[i] if i < len(self.surfs) else self.surfs[0] screen.blit(surf, (int(self.x - surf.get_width() / 2 - cam_x), @@ -668,9 +679,11 @@ def run_level(clock, assets, audio_paths, map_name='W1L1'): if water_t >= WATER_DAMAGE_EVERY: water_t = 0.0 hearts -= 1 + player.hurt_t = 0.9 # Schadens-Blinken if hearts <= 0 and player.d.get('death_frame') is not None: # Tod-Animation starten: erschrockener Frame, Flug nach # oben aus dem Bild, Tuch/Kappe faellt herunter + player.hurt_t = 0.0 # kein Blink-Toggle waehrend der Anim player.force_frame = player.d['death_frame'] dying = dict(t=0.0, vy=-260.0, drop_y=player.y - 40.0, drop_vy=-30.0)