Refactor unit classes to reduce code duplication and improve maintainability

- Updated the Unit base class to include common attributes and methods for all units.
- Refactored Bomb, Point, and Rat classes to inherit from the new Unit class structure.
- Implemented a consistent die method across units for better cleanup.
- Removed redundant code in unit initialization and added specific attributes where necessary.
- Deleted obsolete configuration file and added a comprehensive architecture guide for future reference.
This commit is contained in:
2025-08-13 17:42:45 +02:00
parent 3266ce8209
commit 088ae02080
18 changed files with 484 additions and 32497 deletions
+13 -15
View File
@@ -8,16 +8,9 @@ AGE_THRESHOLD = 200
class Bomb(Unit):
def __init__(self, game, position=(0,0), id=None):
super().__init__(position)
self.id = id if id else uuid.uuid4()
self.game = game
self.position = position
self.bbox = (0, 0, 0, 0)
self.stop = 0
self.age = 0
self.speed = 4
self.partial_move = 0
self.position_before = position
super().__init__(game, position, id)
# Specific attributes for bombs
self.speed = 4 # Bombs age faster
self.fight = False
def move(self):
@@ -54,16 +47,21 @@ class Timer(Bomb):
self.die()
def die(self, unit=None, score=None):
"""Handle bomb explosion and chain reactions."""
score = 10
print("BOOM")
if not unit:
unit = self
target_unit = unit if unit else self
self.game.play_sound("BOMB.WAV")
# Use base class cleanup with error handling
try:
self.game.units.pop(unit.id)
if target_unit.id in self.game.units:
self.game.units.pop(target_unit.id)
except:
print(f"Unit {unit.id} already dead")
self.game.spawn_unit(Explosion, unit.position)
print(f"Unit {target_unit.id} already dead")
# Bomb-specific behavior: create explosion
self.game.spawn_unit(Explosion, target_unit.position)
for direction in ["N", "S", "E", "W"]:
x, y = unit.position
while True:
+7 -13
View File
@@ -8,16 +8,9 @@ AGE_THRESHOLD = 200
class Point(Unit):
def __init__(self, game, position=(0,0), id=None, value=5):
super().__init__(position)
self.id = id if id else uuid.uuid4()
self.game = game
self.position = position
self.bbox = (0, 0, 0, 0)
self.stop = 0
self.age = 0
self.speed = 4
self.partial_move = 0
self.position_before = position
super().__init__(game, position, id)
# Specific attributes for points
self.speed = 4 # Points age faster
self.fight = False
self.value = value
self.game.add_point(self.value)
@@ -31,9 +24,10 @@ class Point(Unit):
pass
def die(self, unit=None, score=None):
if not unit:
unit = self
self.game.units.pop(unit.id)
"""Handle point cleanup. Points just disappear when they expire."""
target_unit = unit if unit else self
# Use base class cleanup
super().die()
def draw(self):
+16 -18
View File
@@ -13,17 +13,12 @@ BABY_INTERVAL = 50
class Rat(Unit):
def __init__(self, game, position=(0,0), id=None):
super().__init__(position)
self.id = id if id else uuid.uuid4()
self.game = game
self.position = self.find_next_position()
self.bbox = (0, 0, 0, 0)
self.stop = 0
self.age = 0
self.speed = .10
self.partial_move = 0
self.position_before = position
super().__init__(game, position, id)
# Specific attributes for rats
self.speed = 0.10 # Rats are slower
self.fight = False
# Initialize position using pathfinding
self.position = self.find_next_position()
def calculate_rat_direction(self):
x, y = self.position
@@ -94,10 +89,13 @@ class Rat(Unit):
self.fuck(unit)
def die(self, unit=None, score=10):
if not unit:
unit = self
self.game.units.pop(unit.id)
self.game.spawn_unit(Point, unit.position_before, value=score)
"""Handle rat death and spawn points."""
target_unit = unit if unit else self
# Use base class cleanup
if target_unit.id in self.game.units:
self.game.units.pop(target_unit.id)
# Rat-specific behavior: spawn points
self.game.spawn_unit(Point, target_unit.position_before, value=score)
def draw(self):
start_perf = self.game.engine.get_perf_counter()
@@ -121,8 +119,8 @@ class Rat(Unit):
#self.game.engine.draw_rectangle(self.bbox[0], self.bbox[1], self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1], "unit")
class Male(Rat):
def __init__(self, map, position=(0,0), id=None):
super().__init__(map, position, id)
def __init__(self, game, position=(0,0), id=None):
super().__init__(game, position, id)
self.sex = "MALE"
def fuck(self, unit):
@@ -134,11 +132,11 @@ class Male(Rat):
unit.babies = random.randint(1, 3)
class Female(Rat):
def __init__(self, map, position=(0,0), id=None):
def __init__(self, game, position=(0,0), id=None):
super().__init__(game, position, id)
self.sex = "FEMALE"
self.pregnant = False
self.babies = 0
super().__init__(map, position, id)
def procreate(self):
self.pregnant -= 1
+57 -14
View File
@@ -1,27 +1,70 @@
class Unit:
from abc import ABC, abstractmethod
import uuid
class Unit(ABC):
"""
A class to represent a unit in the game.
Abstract base class for all game units.
Attributes
----------
id : UUID
Unique identifier for the unit.
game : Game
Reference to the main game object.
position : tuple
The current position of the unit (default is (0, 0)).
The current position of the unit (x, y).
position_before : tuple
The position of the unit before the last update.
state : int
The current state of the unit (default is 0).
age : int
The age of the unit in game ticks.
speed : float
The delay between updates in seconds (default is 0.05).
partial_move : int
The partial move value (default is 0).
Movement speed of the unit.
partial_move : float
Partial movement progress for smooth animation.
bbox : tuple
Bounding box for collision detection (x1, y1, x2, y2).
stop : int
Number of ticks to remain stationary.
Methods
-------
__init__(self, position=(0,0))
Initializes the unit with a given position.
move()
Update unit position and state (must be implemented by subclasses).
draw()
Render the unit on screen (must be implemented by subclasses).
collisions()
Handle collisions with other units (optional override).
die()
Remove unit from game and handle cleanup.
"""
def __init__(self, position=(0,0)):
def __init__(self, game, position=(0, 0), id=None):
"""Initialize a unit with game reference and position."""
self.id = id if id else uuid.uuid4()
self.game = game
self.position = position
self.position_before = self.position
self.state = 0
self.partial_move = 1
self.position_before = position
self.age = 0
self.speed = 1.0
self.partial_move = 0
self.bbox = (0, 0, 0, 0)
self.stop = 0
@abstractmethod
def move(self):
"""Update unit position and state. Must be implemented by subclasses."""
pass
@abstractmethod
def draw(self):
"""Render the unit on screen. Must be implemented by subclasses."""
pass
def collisions(self):
"""Handle collisions with other units. Default implementation does nothing."""
pass
def die(self):
"""Remove unit from game and handle basic cleanup."""
if self.id in self.game.units:
self.game.units.pop(self.id)