v1.1: Performance optimizations and bug fixes
Major improvements: - NumPy-based collision system supporting 200+ units (~3ms/frame) - Spatial hashing with vectorized distance calculations - 4-pass game loop ensuring correct collision timing - Blood overlay system with pre-generated stain pool - Cached render positions and viewport bounds - Spawn protection preventing rats spawning on weapons Bug fixes: - Fixed bombs not killing rats (collision system timing) - Fixed gas not affecting rats (collision system timing) - Fixed rats spawning on weapons (added has_weapon_at check) - Fixed AttributeError with Gas collisions (added isinstance check) - Fixed blood stain transparency (RGBA + SDL_BLENDMODE_BLEND) - Reduced point lifetime from 200 to 90 frames (~1.5s) - Blood layer now clears on game restart Technical changes: - Added engine/collision_system.py with CollisionLayer enum - Updated all units to use collision layers - Pre-allocate NumPy arrays with capacity management - Hybrid collision approach (<10 simple, ≥10 vectorized) - Python 3.13 compatibility
This commit is contained in:
Binary file not shown.
Binary file not shown.
+2
-2
@@ -2,8 +2,8 @@ from .unit import Unit
|
||||
import random
|
||||
import uuid
|
||||
|
||||
# Costanti
|
||||
AGE_THRESHOLD = 200
|
||||
# Costanti - Points disappear after ~1.5 seconds (90 frames at 60 FPS)
|
||||
AGE_THRESHOLD = 90
|
||||
|
||||
|
||||
from .unit import Unit
|
||||
|
||||
+55
-15
@@ -19,6 +19,7 @@ class Rat(Unit):
|
||||
self.speed = 0.10 # Rats are slower
|
||||
self.fight = False
|
||||
self.gassed = 0
|
||||
self.direction = "DOWN" # Default direction
|
||||
# Initialize position using pathfinding
|
||||
self.position = self.find_next_position()
|
||||
|
||||
@@ -72,6 +73,31 @@ class Rat(Unit):
|
||||
self.position = self.find_next_position()
|
||||
self.direction = self.calculate_rat_direction()
|
||||
|
||||
# Pre-calculate render position for draw() - optimization
|
||||
self._update_render_position()
|
||||
|
||||
def _update_render_position(self):
|
||||
"""Pre-calculate rendering position and bbox during move() to optimize draw()"""
|
||||
sex = self.sex if self.age > AGE_THRESHOLD else "BABY"
|
||||
|
||||
# Get cached image size instead of calling get_image_size()
|
||||
image_size = self.game.rat_image_sizes[sex][self.direction]
|
||||
|
||||
# Calculate partial movement offset
|
||||
if self.direction in ["UP", "DOWN"]:
|
||||
partial_x = 0
|
||||
partial_y = self.partial_move * self.game.cell_size * (1 if self.direction == "DOWN" else -1)
|
||||
else:
|
||||
partial_x = self.partial_move * self.game.cell_size * (1 if self.direction == "RIGHT" else -1)
|
||||
partial_y = 0
|
||||
|
||||
# Calculate final render position
|
||||
self.render_x = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 + partial_x
|
||||
self.render_y = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 + partial_y
|
||||
|
||||
# Update bbox for collision system
|
||||
self.bbox = (self.render_x, self.render_y, self.render_x + image_size[0], self.render_y + image_size[1])
|
||||
|
||||
def collisions(self):
|
||||
"""
|
||||
Optimized collision detection using the vectorized collision system.
|
||||
@@ -94,6 +120,10 @@ class Rat(Unit):
|
||||
for _, other_id in collisions:
|
||||
other_unit = self.game.get_unit_by_id(other_id)
|
||||
|
||||
# Skip if not another Rat
|
||||
if not isinstance(other_unit, Rat):
|
||||
continue
|
||||
|
||||
if not other_unit or other_unit.age < AGE_THRESHOLD:
|
||||
continue
|
||||
|
||||
@@ -128,25 +158,35 @@ class Rat(Unit):
|
||||
self.game.add_blood_stain(death_position)
|
||||
|
||||
def draw(self):
|
||||
start_perf = self.game.render_engine.get_perf_counter()
|
||||
direction = self.calculate_rat_direction()
|
||||
|
||||
"""Optimized draw using pre-calculated positions from move()"""
|
||||
sex = self.sex if self.age > AGE_THRESHOLD else "BABY"
|
||||
image = self.game.rat_assets_textures[sex][direction]
|
||||
image_size = self.game.render_engine.get_image_size(image)
|
||||
self.rat_image = image
|
||||
partial_x, partial_y = 0, 0
|
||||
image = self.game.rat_assets_textures[sex][self.direction]
|
||||
|
||||
if direction in ["UP", "DOWN"]:
|
||||
partial_y = self.partial_move * self.game.cell_size * (1 if direction == "DOWN" else -1)
|
||||
else:
|
||||
partial_x = self.partial_move * self.game.cell_size * (1 if direction == "RIGHT" else -1)
|
||||
# Calculate render position if not yet set (first frame)
|
||||
if not hasattr(self, 'render_x'):
|
||||
self._calculate_render_position()
|
||||
|
||||
x_pos = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 + partial_x
|
||||
y_pos = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 + partial_y
|
||||
self.game.render_engine.draw_image(x_pos, y_pos, image, anchor="nw", tag="unit")
|
||||
self.bbox = (x_pos, y_pos, x_pos + image_size[0], y_pos + image_size[1])
|
||||
# Use pre-calculated positions
|
||||
self.game.render_engine.draw_image(self.render_x, self.render_y, image, anchor="nw", tag="unit")
|
||||
# bbox already updated in _update_render_position()
|
||||
#self.game.render_engine.draw_rectangle(self.bbox[0], self.bbox[1], self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1], "unit")
|
||||
|
||||
def _calculate_render_position(self):
|
||||
"""Calculate render position and bbox (used when render_x not yet set)"""
|
||||
sex = self.sex if self.age > AGE_THRESHOLD else "BABY"
|
||||
image_size = self.game.render_engine.get_image_size(
|
||||
self.game.rat_assets_textures[sex][self.direction]
|
||||
)
|
||||
|
||||
partial_x, partial_y = 0, 0
|
||||
if self.direction in ["UP", "DOWN"]:
|
||||
partial_y = self.partial_move * self.game.cell_size * (1 if self.direction == "DOWN" else -1)
|
||||
else:
|
||||
partial_x = self.partial_move * self.game.cell_size * (1 if self.direction == "RIGHT" else -1)
|
||||
|
||||
self.render_x = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 + partial_x
|
||||
self.render_y = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 + partial_y
|
||||
self.bbox = (self.render_x, self.render_y, self.render_x + image_size[0], self.render_y + image_size[1])
|
||||
|
||||
class Male(Rat):
|
||||
def __init__(self, game, position=(0,0), id=None):
|
||||
|
||||
Reference in New Issue
Block a user