Implement optimized collision detection system using NumPy

- Introduced a hybrid collision detection approach that utilizes NumPy for vectorized operations, improving performance for games with many entities (200+).
- Added a spatial grid for efficient lookups and AABB (Axis-Aligned Bounding Box) collision detection.
- Implemented a new `CollisionSystem` class with methods for registering units, checking collisions, and managing spatial data.
- Created performance tests to benchmark the new collision system against the old O(n²) method, demonstrating significant speed improvements.
- Updated existing code to integrate the new collision detection system and ensure compatibility with game logic.
This commit is contained in:
2025-10-24 19:13:30 +02:00
parent 47028c95ae
commit 12836dd2d2
17 changed files with 1591 additions and 64 deletions
+34 -20
View File
@@ -1,5 +1,6 @@
from .unit import Unit
from .points import Point
from engine.collision_system import CollisionLayer
import random
import uuid
@@ -13,7 +14,7 @@ BABY_INTERVAL = 50
class Rat(Unit):
def __init__(self, game, position=(0,0), id=None):
super().__init__(game, position, id)
super().__init__(game, position, id, collision_layer=CollisionLayer.RAT)
# Specific attributes for rats
self.speed = 0.10 # Rats are slower
self.fight = False
@@ -72,30 +73,43 @@ class Rat(Unit):
self.direction = self.calculate_rat_direction()
def collisions(self):
"""
Optimized collision detection using the vectorized collision system.
Uses spatial hashing and numpy for efficient checks with 200+ units.
"""
OVERLAP_TOLERANCE = self.game.cell_size // 4
# Only adult rats can collide for reproduction/fighting
if self.age < AGE_THRESHOLD:
return
units = []
units.extend(self.game.unit_positions.get(self.position_before, []))
units.extend(self.game.unit_positions.get(self.position, []))
for unit in units:
if unit.id == self.id or unit.age < AGE_THRESHOLD or self.position != unit.position_before:
continue
x1, y1, x2, y2 = self.bbox
ox1, oy1, ox2, oy2 = unit.bbox
# Get collisions from the optimized collision system
collisions = self.game.collision_system.get_collisions_for_unit(
self.id,
CollisionLayer.RAT,
tolerance=OVERLAP_TOLERANCE
)
# Process each collision
for _, other_id in collisions:
other_unit = self.game.get_unit_by_id(other_id)
# Verifica se c'è collisione con una tolleranza di sovrapposizione
if (x1 < ox2 - OVERLAP_TOLERANCE and
x2 > ox1 + OVERLAP_TOLERANCE and
y1 < oy2 - OVERLAP_TOLERANCE and
y2 > oy1 + OVERLAP_TOLERANCE):
if self.id in self.game.units and unit.id in self.game.units:
if self.sex == unit.sex and self.fight:
self.die(unit)
elif self.sex != unit.sex:
if "fuck" in dir(self):
self.fuck(unit)
if not other_unit or other_unit.age < AGE_THRESHOLD:
continue
# Check if units are actually moving towards each other
if self.position != other_unit.position_before:
continue
# Both units still exist in game
if self.id in self.game.units and other_id in self.game.units:
if self.sex == other_unit.sex and self.fight:
# Same sex + fight mode = combat
self.die(other_unit)
elif self.sex != other_unit.sex:
# Different sex = reproduction
if "fuck" in dir(self):
self.fuck(other_unit)
def die(self, unit=None, score=10):
"""Handle rat death and spawn points."""