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:
Binary file not shown.
Binary file not shown.
+39
-24
@@ -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"]
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user