Fix bomb explosions not killing rats and remove tracked pycache

- Move Timer explosion from move() to collisions() so all units are
  registered in the collision system before the kill query runs.
- Explosion units now set a bbox and kill rats that touch them.
- Guard Rat.draw() so dead rats are not drawn.
- Remove units/__pycache__ files from tracking.
This commit is contained in:
Matteo Benedetto
2026-06-16 19:15:35 +02:00
parent c7ed24483d
commit 3e8cd97fda
4 changed files with 41 additions and 24 deletions
Binary file not shown.
Binary file not shown.
+39 -24
View File
@@ -55,32 +55,31 @@ class Timer(Bomb):
def move(self):
self.age += self.speed
if self.age == AGE_THRESHOLD:
self.die()
if self.age >= AGE_THRESHOLD and not getattr(self, "exploded", False):
self.exploding = True
def die(self, unit=None, score=None):
"""Handle bomb explosion and chain reactions using vectorized collision system."""
def collisions(self):
"""Explode in Pass 2 when every unit is registered in the collision system."""
if getattr(self, "exploding", False) and not getattr(self, "exploded", False):
self.explode()
def explode(self):
"""Handle bomb explosion and chain reactions."""
score = 10
print("BOOM")
target_unit = unit if unit else self
self.game.render_engine.play_sound("BOMB.WAV")
self.exploded = True
# Use base class cleanup with error handling
try:
if target_unit.id in self.game.units:
self.game.units.pop(target_unit.id)
except:
print(f"Unit {target_unit.id} already dead")
# Remove bomb
if self.id in self.game.units:
self.game.units.pop(self.id)
# Bomb-specific behavior: create explosion
self.game.unit_manager.spawn_unit(Explosion, target_unit.position)
# Collect all explosion positions using vectorized approach
# Collect all explosion positions
explosion_positions = []
# Check for chain reactions in all four directions
for direction in ["N", "S", "E", "W"]:
x, y = target_unit.position
x, y = self.position
while True:
if not self.game.map.is_wall(x, y):
explosion_positions.append((x, y))
@@ -95,28 +94,30 @@ class Timer(Bomb):
elif direction == "W":
x -= 1
# Create all explosions at once
# Create visual explosions
for pos in explosion_positions:
self.game.unit_manager.spawn_unit(Explosion, pos)
# Use optimized collision system to get all rats in explosion area
# This replaces the nested loop with a single vectorized operation
# Kill all rats in explosion area (Pass 2: all units registered)
victim_ids = self.game.collision_system.get_units_in_area(
explosion_positions,
explosion_positions,
layer_filter=CollisionLayer.RAT
)
# Kill all victims with score multiplier
for victim_id in victim_ids:
victim = self.game.unit_manager.get_unit_by_id(victim_id)
if victim and victim.id in self.game.units:
# Determine position based on partial_move
victim_pos = victim.position if victim.partial_move >= 0.5 else victim.position_before
if victim_pos in explosion_positions:
if victim.position in explosion_positions or victim.position_before in explosion_positions:
victim.die(score=score)
if score < 160:
score *= 2
def draw(self):
"""Don't draw a bomb that has already exploded."""
if getattr(self, "exploded", False):
return
super().draw()
class Explosion(Bomb):
def __init__(self, game, position=(0,0), id=None):
@@ -129,6 +130,20 @@ class Explosion(Bomb):
self.age += self.speed
if self.age >= AGE_THRESHOLD:
self.die()
# Set bbox so lingering explosions can kill rats via collision system
x = self.position[0] * self.game.cell_size
y = self.position[1] * self.game.cell_size
self.bbox = (float(x), float(y), float(x + self.game.cell_size), float(y + self.game.cell_size))
def collisions(self):
"""Lingering explosion kills any rat that touches it."""
victim_ids = self.game.collision_system.get_collisions_for_unit(
self.id, CollisionLayer.EXPLOSION, tolerance=0
)
for _, victim_id in victim_ids:
victim = self.game.unit_manager.get_unit_by_id(victim_id)
if victim and victim.type in [UnitType.RAT_MALE, UnitType.RAT_FEMALE] and victim.id in self.game.units:
victim.die(score=10)
def draw(self):
image = self.game.graphics.assets["BMP_EXPLOSION"]
+2
View File
@@ -171,6 +171,8 @@ class Rat(Unit):
def draw(self):
"""Optimized draw using pre-calculated positions from move()"""
if self.id not in self.game.units:
return
sex = self.sex if self.age > AGE_THRESHOLD else "BABY"
image = self.game.graphics.rat_assets_textures[sex][self.direction]
image_size = self.game.graphics.rat_image_sizes[sex][self.direction]