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
+35 -3
View File
@@ -5,6 +5,7 @@ import os
import json
from engine import maze, sdl2 as engine, controls, graphics, unit_manager, scoring
from engine.collision_system import CollisionSystem
from units import points
from engine.user_profile_integration import UserProfileIntegration, get_global_leaderboard
@@ -49,8 +50,18 @@ class MiceMaze(
self.scroll_cursor()
self.points = 0
self.units = {}
# Initialize optimized collision system with NumPy
self.collision_system = CollisionSystem(
self.cell_size,
self.map.width,
self.map.height
)
# Keep old dictionaries for backward compatibility (can be removed later)
self.unit_positions = {}
self.unit_positions_before = {}
self.scrolling_direction = None
self.game_status = "start_menu"
self.game_end = (False, None)
@@ -150,15 +161,36 @@ class MiceMaze(
self.render_engine.delete_tag("unit")
self.render_engine.delete_tag("effect")
self.render_engine.draw_pointer(self.pointer[0] * self.cell_size, self.pointer[1] * self.cell_size)
# Clear collision system for new frame
self.collision_system.clear()
self.unit_positions.clear()
self.unit_positions_before.clear()
for unit in self.units.values():
self.unit_positions.setdefault(unit.position, []).append(unit)
self.unit_positions_before.setdefault(unit.position_before, []).append(unit)
# First pass: move all units and update their positions
for unit in self.units.copy().values():
unit.move()
# Second pass: register all units in collision system and draw
for unit in self.units.values():
# Register unit in optimized collision system
self.collision_system.register_unit(
unit.id,
unit.bbox,
unit.position,
unit.position_before,
unit.collision_layer
)
# Maintain backward compatibility dictionaries (can be removed later)
self.unit_positions.setdefault(unit.position, []).append(unit)
self.unit_positions_before.setdefault(unit.position_before, []).append(unit)
# Third pass: check collisions and draw
for unit in self.units.copy().values():
unit.collisions()
unit.draw()
self.render_engine.update_status(f"Mice: {self.count_rats()} - Points: {self.points}")
self.refill_ammo()
self.render_engine.update_ammo(self.ammo, self.assets)