Enhance simulation performance and add sprint mode functionality
Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 30s
Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 30s
This commit is contained in:
parent
8a53d4ac37
commit
deee83edb3
@ -25,9 +25,9 @@ CELL_SIZE = 20
|
||||
RENDER_BUFFER = 50
|
||||
|
||||
# Performance settings
|
||||
DEFAULT_TPS = 20
|
||||
DEFAULT_TPS = 40
|
||||
MAX_FPS = 180
|
||||
TURBO_MULTIPLIER = 4
|
||||
TURBO_MULTIPLIER = 8
|
||||
|
||||
# Camera settings
|
||||
DEFAULT_CAMERA_SPEED = 700
|
||||
@ -44,6 +44,7 @@ SELECTION_THRESHOLD = 3 # pixels
|
||||
|
||||
# Simulation settings
|
||||
FOOD_SPAWNING = True
|
||||
FOOD_OBJECTS_COUNT = 100
|
||||
RANDOM_SEED = 0
|
||||
|
||||
# Vector visualization settings
|
||||
@ -58,7 +59,7 @@ DIRECTION_TIP_SIZE = 3
|
||||
MAX_ACCELERATION = 0.1
|
||||
MAX_ANGULAR_ACCELERATION = 0.25
|
||||
MAX_VELOCITY = 0.5
|
||||
MAX_ROTATIONAL_VELOCITY = 6
|
||||
MAX_ROTATIONAL_VELOCITY = 3
|
||||
|
||||
KEYMAP_LEGEND = [
|
||||
("WASD", "Move camera"),
|
||||
|
||||
@ -25,6 +25,7 @@ class InputHandler:
|
||||
# Speed control
|
||||
self.tps = DEFAULT_TPS
|
||||
self.default_tps = DEFAULT_TPS
|
||||
self.sprint_mode = False
|
||||
|
||||
def handle_events(self, events):
|
||||
"""Process all pygame events and return game state."""
|
||||
@ -74,6 +75,8 @@ class InputHandler:
|
||||
self.tps = self.default_tps * TURBO_MULTIPLIER
|
||||
elif event.key == pygame.K_r:
|
||||
self.camera.reset_position()
|
||||
elif event.key == pygame.K_RSHIFT:
|
||||
self.sprint_mode = True # Enter sprint mode
|
||||
|
||||
return running
|
||||
|
||||
@ -81,6 +84,8 @@ class InputHandler:
|
||||
"""Handle keyup events."""
|
||||
if event.key == pygame.K_LSHIFT:
|
||||
self.tps = self.default_tps
|
||||
if event.key == pygame.K_RSHIFT:
|
||||
self.sprint_mode = False # Exit sprint mode
|
||||
|
||||
def _handle_mouse_down(self, event):
|
||||
"""Handle mouse button down events."""
|
||||
|
||||
@ -39,9 +39,12 @@ class SimulationEngine:
|
||||
random.seed(RANDOM_SEED)
|
||||
|
||||
if FOOD_SPAWNING:
|
||||
world.add_object(FoodObject(Position(x=random.randint(-100, 100), y=random.randint(-100, 100))))
|
||||
for _ in range(FOOD_OBJECTS_COUNT):
|
||||
x = random.randint(-100, 100)
|
||||
y = random.randint(-100, 100)
|
||||
world.add_object(FoodObject(Position(x=x, y=y)))
|
||||
|
||||
for _ in range(1):
|
||||
for _ in range(20):
|
||||
world.add_object(DefaultCell(Position(x=random.randint(-100, 100), y=random.randint(-100, 100)), Rotation(angle=0)))
|
||||
|
||||
return world
|
||||
@ -60,6 +63,30 @@ class SimulationEngine:
|
||||
# Handle events
|
||||
self.running = self.input_handler.handle_events(pygame.event.get())
|
||||
|
||||
if self.input_handler.sprint_mode:
|
||||
# Sprint mode: run as many ticks as possible, skip rendering
|
||||
current_time = time.perf_counter()
|
||||
while True:
|
||||
self.input_handler.update_selected_objects()
|
||||
self.world.tick_all()
|
||||
self.tick_counter += 1
|
||||
self.total_ticks += 1
|
||||
# Optionally break after some time to allow event processing
|
||||
if time.perf_counter() - current_time > 0.05: # ~50ms per batch
|
||||
break
|
||||
# Update TPS every second
|
||||
if time.perf_counter() - self.last_tps_time >= 1.0:
|
||||
self.actual_tps = self.tick_counter
|
||||
self.tick_counter = 0
|
||||
self.last_tps_time = time.perf_counter()
|
||||
# No rendering or camera update
|
||||
|
||||
self.renderer.clear_screen()
|
||||
self.hud.render_sprint_debug(self.screen, self.actual_tps, self.total_ticks)
|
||||
pygame.display.flip()
|
||||
self.clock.tick(MAX_FPS)
|
||||
return
|
||||
|
||||
if not self.input_handler.is_paused:
|
||||
current_time = time.perf_counter()
|
||||
while current_time - self.last_tick_time >= tick_interval:
|
||||
|
||||
15
ui/hud.py
15
ui/hud.py
@ -462,3 +462,18 @@ class HUD:
|
||||
for surf in tooltip_surfs:
|
||||
screen.blit(surf, (tooltip_rect.left + TOOLTIP_PADDING_X, y))
|
||||
y += surf.get_height() + TOOLTIP_LINE_SPACING
|
||||
|
||||
def render_sprint_debug(self, screen, actual_tps, total_ticks):
|
||||
"""Render sprint debug info: header, TPS, and tick count."""
|
||||
header = self.font.render("Sprinting...", True, (255, 200, 0))
|
||||
tps_text = self.font.render(f"TPS: {actual_tps}", True, (255, 255, 255))
|
||||
ticks_text = self.font.render(f"Ticks: {total_ticks}", True, (255, 255, 255))
|
||||
|
||||
y = SCREEN_HEIGHT // 2 - 40
|
||||
header_rect = header.get_rect(center=(SCREEN_WIDTH // 2, y))
|
||||
tps_rect = tps_text.get_rect(center=(SCREEN_WIDTH // 2, y + 40))
|
||||
ticks_rect = ticks_text.get_rect(center=(SCREEN_WIDTH // 2, y + 80))
|
||||
|
||||
screen.blit(header, header_rect)
|
||||
screen.blit(tps_text, tps_rect)
|
||||
screen.blit(ticks_text, ticks_rect)
|
||||
|
||||
@ -250,6 +250,8 @@ class DefaultCell(BaseEntity):
|
||||
self.rotational_velocity: int = 0
|
||||
self.angular_acceleration: int = 0
|
||||
|
||||
self.energy: int = 1000
|
||||
|
||||
self.behavioral_model: CellBrain = CellBrain()
|
||||
|
||||
self.max_visual_width: int = 10
|
||||
@ -274,6 +276,17 @@ class DefaultCell(BaseEntity):
|
||||
:return: Self.
|
||||
"""
|
||||
|
||||
if self.energy == 0:
|
||||
# too hungry lmao
|
||||
self.flag_for_death()
|
||||
return self
|
||||
|
||||
self.energy -= 1
|
||||
|
||||
if self.tick_count > 2000:
|
||||
# too old lmao
|
||||
self.flag_for_death()
|
||||
|
||||
if interactable is None:
|
||||
interactable = []
|
||||
|
||||
@ -287,14 +300,40 @@ class DefaultCell(BaseEntity):
|
||||
food_object = FoodObject(self.position)
|
||||
|
||||
angle_between_food = self.calculate_angle_between_food(self.position.get_position(), self.rotation.get_rotation(), food_object.position.get_position())
|
||||
distance_to_food = get_distance_between_objects(self, food_object)
|
||||
|
||||
if distance_to_food < self.max_visual_width and food_objects:
|
||||
self.energy += 100
|
||||
food_object.flag_for_death()
|
||||
return self
|
||||
|
||||
if self.energy >= 1500:
|
||||
# too much energy, split
|
||||
duplicate_x, duplicate_y = self.position.get_position()
|
||||
duplicate_x += random.randint(-self.interaction_radius, self.interaction_radius)
|
||||
duplicate_y += random.randint(-self.interaction_radius, self.interaction_radius)
|
||||
|
||||
duplicate_x_2, duplicate_y_2 = self.position.get_position()
|
||||
duplicate_x_2 += random.randint(-self.interaction_radius, self.interaction_radius)
|
||||
duplicate_y_2 += random.randint(-self.interaction_radius, self.interaction_radius)
|
||||
|
||||
new_cell = DefaultCell(Position(x=int(duplicate_x), y=int(duplicate_y)), Rotation(angle=random.randint(0, 359)))
|
||||
new_cell.set_brain(self.behavioral_model.mutate(1))
|
||||
|
||||
new_cell_2 = DefaultCell(Position(x=int(duplicate_x_2), y=int(duplicate_y_2)), Rotation(angle=random.randint(0, 359)))
|
||||
new_cell_2.set_brain(self.behavioral_model.mutate(1))
|
||||
|
||||
return [new_cell, new_cell_2]
|
||||
|
||||
input_data = {
|
||||
"distance": get_distance_between_objects(self, food_object),
|
||||
"distance": distance_to_food,
|
||||
"angle": angle_between_food,
|
||||
}
|
||||
|
||||
output_data = self.behavioral_model.tick(input_data)
|
||||
|
||||
# everything below this point is physics simulation and needs to be extracted to a separate class
|
||||
|
||||
# clamp accelerations
|
||||
output_data["linear_acceleration"] = max(-MAX_ACCELERATION, min(MAX_ACCELERATION, output_data["linear_acceleration"]))
|
||||
output_data["angular_acceleration"] = max(-MAX_ANGULAR_ACCELERATION, min(MAX_ANGULAR_ACCELERATION, output_data["angular_acceleration"]))
|
||||
@ -408,4 +447,5 @@ class DefaultCell(BaseEntity):
|
||||
position = f"({round(self.position.x, 1)}, {round(self.position.y, 1)})"
|
||||
velocity = tuple(round(value, 1) for value in self.velocity)
|
||||
acceleration = tuple(round(value, 1) for value in self.acceleration)
|
||||
return f"DefaultCell(position={position}, velocity={velocity}, acceleration={acceleration}"
|
||||
rotation = round(self.rotation.get_rotation(), 1)
|
||||
return f"DefaultCell(position={position}, velocity={velocity}, acceleration={acceleration}, rotation={rotation}, energy={self.energy}, age={self.tick_count})"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user