import pygame import time import random import sys from world.base.brain import CellBrain, FlexibleNeuralNetwork from world.world import World, Position, Rotation from world.objects import FoodObject, DefaultCell from world.simulation_interface import Camera from config.constants import * from core.input_handler import InputHandler from core.renderer import Renderer from ui.hud import HUD class SimulationEngine: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), vsync=1) pygame.display.set_caption("Dynamic Abstraction System Testing") self.clock = pygame.time.Clock() self.camera = Camera(SCREEN_WIDTH, SCREEN_HEIGHT, RENDER_BUFFER) self.last_tick_time = time.perf_counter() self.last_tps_time = time.perf_counter() self.tick_counter = 0 self.actual_tps = 0 self.total_ticks = 0 self.world = self._setup_world() self.input_handler = InputHandler(self.camera, self.world) self.renderer = Renderer(self.screen) self.hud = HUD() self.running = True @staticmethod def _setup_world(): world = World(CELL_SIZE, (CELL_SIZE * GRID_WIDTH, CELL_SIZE * GRID_HEIGHT)) random.seed(RANDOM_SEED) half_width = GRID_WIDTH * CELL_SIZE // 2 half_height = GRID_HEIGHT * CELL_SIZE // 2 if FOOD_SPAWNING: for _ in range(FOOD_OBJECTS_COUNT): x = random.randint(-half_width, half_width) y = random.randint(-half_height, half_height) world.add_object(FoodObject(Position(x=x, y=y))) for _ in range(300): new_cell = DefaultCell(Position(x=random.randint(-half_width, half_width), y=random.randint(-half_height, half_height)), Rotation(angle=0)) new_cell.behavioral_model = new_cell.behavioral_model.mutate(3) world.add_object(new_cell) return world def run(self): while self.running: self._handle_frame() pygame.quit() sys.exit() def _handle_frame(self): deltatime = self.clock.get_time() / 1000.0 tick_interval = 1.0 / self.input_handler.tps # Handle events events = pygame.event.get() self.running = self.input_handler.handle_events(events, self.hud.manager) 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: self.last_tick_time += tick_interval self.tick_counter += 1 self.total_ticks += 1 self.input_handler.update_selected_objects() self.world.tick_all() self.hud.manager.update(deltatime) if current_time - self.last_tps_time >= 1.0: self.actual_tps = self.tick_counter self.tick_counter = 0 self.last_tps_time += 1.0 else: self.last_tick_time = time.perf_counter() self.last_tps_time = time.perf_counter() self.hud.manager.draw_ui(self.screen) self._update(deltatime) self._render() def _update(self, deltatime): keys = pygame.key.get_pressed() self.input_handler.update_camera(keys, deltatime) def _render(self): self.renderer.clear_screen() self.renderer.draw_grid(self.camera, self.input_handler.show_grid) self.renderer.render_world(self.world, self.camera) self.renderer.render_interaction_radius(self.world, self.camera, self.input_handler.selected_objects, self.input_handler.show_interaction_radius) self.renderer.render_selection_rectangle(self.input_handler.get_selection_rect()) self.renderer.render_selected_objects_outline(self.input_handler.selected_objects, self.camera) self.hud.render_mouse_position(self.screen, self.camera) self.hud.render_fps(self.screen, self.clock) self.hud.render_tps(self.screen, self.actual_tps) self.hud.render_tick_count(self.screen, self.total_ticks) self.hud.render_selected_objects_info(self.screen, self.input_handler.selected_objects) self.hud.render_legend(self.screen, self.input_handler.show_legend) self.hud.render_pause_indicator(self.screen, self.input_handler.is_paused) if self.input_handler.selected_objects: self.hud.render_neural_network_visualization(self.screen, self.input_handler.selected_objects[0]) pygame.display.flip() self.clock.tick(MAX_FPS)