Commit
the-way-out
v0.2.1
modified audio.py
@@ -104,6 +104,11 @@ def play_music(name):
path = _find(_MUSIC_DIR, name, _MUSIC_EXTS)
if path is None:
stop_music()
# Remember the request even though the file is absent: main.py
# calls play_music every frame, and without this _current_music
# stays None so the unchanged-name guard above never engages —
# a missing track would re-stat the FS and re-fade every frame.
_current_music = name
return
try:
# Fade the outgoing track, then bring the new one up. Single
modified levels.py
@@ -571,6 +571,7 @@ class LevelManager:
self._handle_key()
if (self.boss is not None and self.boss.hp > 0
and self.intro_timer <= 0
and self.player.invuln_timer <= 0
and self.boss.hitbox.colliderect(self.player.hitbox)):
self.player.take_damage(BOSS_TOUCH_DAMAGE)
@@ -583,7 +584,8 @@ class LevelManager:
if en.hp <= 0:
en.kill()
continue
if (self.player.invuln_timer <= 0
if (self.intro_timer <= 0
and self.player.invuln_timer <= 0
and en.hitbox.colliderect(self.player.hitbox)):
self.player.take_damage(en.touch_damage)
self.player.invuln_timer = PLAYER_INVULN_TIME
modified main.py
@@ -194,6 +194,14 @@ while running:
elif game_state == "game":
if level_manager.completed or level_manager.failed:
_leave_game()
# Esc is consumed here. Without this, when the level
# was launched from the editor's Test button
# (return_state == "editor") _leave_game() switches
# to "editor" and the *same* Esc then falls through
# to editor.handle_input below, which reads it as
# "back" and bounces the user past the editor to the
# main menu instead of the editor canvas.
continue
else:
game_state = "paused"
modified units.py
@@ -69,7 +69,9 @@ class Character(pygame.sprite.Sprite):
self.frame_index = 0
self.animation_speed = 10
self.image = self.animations[self.status][self.frame_index]
frames = self.animations[self.status]
self.image = (frames[self.frame_index] if frames
else self._placeholder_frame())
self.rect = self.image.get_rect(topleft=(x, y))
# Smaller collision box, centered on the sprite. Walls are
@@ -315,6 +317,20 @@ class Character(pygame.sprite.Sprite):
# --- animation / tick -------------------------------------------
def _placeholder_frame(self):
"""Visible stand-in when a sprite sheet is missing/renamed.
``load_assets`` returns ``[]`` for an absent PNG ('crash
safety'); this keeps that promise so one bad asset degrades to a
loud magenta box instead of an ``IndexError`` that kills the
whole run. Magenta matches the editor's missing-art marker.
"""
s = max(self.hitbox_size, 16)
surf = pygame.Surface((s, s), pygame.SRCALPHA)
surf.fill((180, 60, 180, 120))
pygame.draw.rect(surf, (180, 60, 180), surf.get_rect(), 2)
return surf
def _apply_overlay(self, frame, color_rgba):
"""Additive RGB overlay that respects the sprite's alpha mask.