Files
mice/units/mine.py
T
enne2 2f8e3e8b28 Fix gas poisoning, explosion hit detection and render order
- Move gas poisoning from Gas.move() to Gas.collisions() so all rats are
  registered in the collision system before the poison query runs.
- Shrink gas and explosion bboxes so rats must be well inside the tile to
  be poisoned/killed.
- Use AABB overlap instead of partial_move threshold for gas poisoning.
- Draw mobile units first, then top-layer effects (gas, mines, bombs,
  explosions) so rats appear under the gas.
- Add draw_on_top hint to Unit base class and top-layer units.
2026-06-16 19:32:50 +02:00

70 lines
2.5 KiB
Python

from .unit import Unit, UnitType
from .bomb import Explosion
from engine.collision_system import CollisionLayer
class Mine(Unit):
draw_on_top = True
def __init__(self, game, position=(0,0), id=None):
super().__init__(game, position, id, collision_layer=CollisionLayer.MINE, unit_type=UnitType.MINE)
self.speed = 1.0 # Mine doesn't move but needs speed for consistency
self.armed = True # Mine is active and ready to explode
def move(self):
"""Mines don't move, but we need to check for collision with rats each frame."""
pass
def collisions(self):
"""Check if a rat steps on the mine using optimized collision system."""
if not self.armed:
return
# Use collision system to check for rats at mine's position_before
victim_ids = self.game.collision_system.get_units_in_cell(
self.position, use_before=True
)
for victim_id in victim_ids:
rat_unit = self.game.unit_manager.get_unit_by_id(victim_id)
if rat_unit and rat_unit.type in [UnitType.RAT_MALE, UnitType.RAT_FEMALE]:
# Mine explodes and kills the rat
self.explode(rat_unit)
break
def explode(self, victim_rat):
"""Mine explodes, killing the rat and destroying itself."""
if not self.armed:
return
self.game.render_engine.play_sound("POISON.WAV")
# Kill the rat that stepped on the mine
if victim_rat.id in self.game.units:
victim_rat.die(score=5)
# Remove the mine from the game
self.die()
def draw(self):
"""Draw the mine using the mine asset."""
if not self.armed:
return
# Use mine asset
image = self.game.graphics.assets["BMP_POISON"]
image_size = self.game.render_engine.get_image_size(image)
# Center the mine in the cell
x_pos = self.position[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2
y_pos = self.position[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2
if self.is_hidden_in_tunnel(image_size, position=self.position):
return
self.game.render_engine.draw_image(x_pos, y_pos, image, anchor="nw", tag="unit")
def die(self, score=None):
"""Remove mine from game and disarm it."""
self.armed = False
super().die(score)