import pygame import time import random import sys from pygame_gui import UIManager 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._init_window() self._init_ui() self._init_simulation() self.running = True def _init_window(self): info = pygame.display.Info() self.window_width = int(info.current_w // 1.5) self.window_height = int(info.current_h // 1.5) self.screen = pygame.display.set_mode( (self.window_width, self.window_height), pygame.RESIZABLE, vsync=1 ) pygame.display.set_caption("Dynamic Abstraction System Testing") self.clock = pygame.time.Clock() def _init_ui(self): self.ui_manager = UIManager((self.window_width, self.window_height)) self.hud = HUD(self.ui_manager, self.window_width, self.window_height) self.hud.update_layout(self.window_width, self.window_height) self._update_simulation_view() def _init_simulation(self): 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.sim_view_rect) self.renderer = Renderer(self.sim_view) def _update_simulation_view(self): viewport_rect = self.hud.get_viewport_rect() self.sim_view_width = viewport_rect.width self.sim_view_height = viewport_rect.height self.sim_view = pygame.Surface((self.sim_view_width, self.sim_view_height)) self.sim_view_rect = self.sim_view.get_rect(topleft=(viewport_rect.left, viewport_rect.top)) self.ui_manager.set_window_resolution((self.window_width, self.window_height)) self.renderer = Renderer(self.sim_view) if hasattr(self, 'camera'): self.camera.screen_width = self.sim_view_width self.camera.screen_height = self.sim_view_height if hasattr(self, 'input_handler'): self.input_handler.update_sim_view_rect(self.sim_view_rect) if not hasattr(self, 'camera'): self.camera = Camera(self.sim_view_width, self.sim_view_height, RENDER_BUFFER) @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 // 2, half_width // 2) y = random.randint(-half_height // 2, half_height // 2) world.add_object(FoodObject(Position(x=x, y=y))) for _ in range(300): new_cell = DefaultCell( Position(x=random.randint(-half_width // 2, half_width // 2), y=random.randint(-half_height // 2, half_height // 2)), Rotation(angle=0) ) new_cell.behavioral_model = new_cell.behavioral_model.mutate(3) world.add_object(new_cell) return world def _count_cells(self): count = 0 for entity in self.world.get_objects(): if isinstance(entity, DefaultCell): count += 1 return count def run(self): print(self.world.current_buffer) 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 events = pygame.event.get() self.running = self.input_handler.handle_events(events, self.hud.manager) self._handle_window_events(events) if self.input_handler.sprint_mode: self._handle_sprint_mode() return # Only process one tick per frame if enough time has passed if not self.input_handler.is_paused: current_time = time.perf_counter() if 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 _handle_window_events(self, events): for event in events: self.hud.process_event(event) if event.type == pygame.VIDEORESIZE: self.window_width, self.window_height = event.w, event.h self.screen = pygame.display.set_mode( (self.window_width, self.window_height), pygame.RESIZABLE ) self._update_simulation_view() self.hud.update_layout(self.window_width, self.window_height) self.hud.update_layout(self.window_width, self.window_height) self._update_simulation_view() def _handle_sprint_mode(self): 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 pygame.event.pump() # Prevent event queue overflow if time.perf_counter() - current_time > 0.05: break 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() self.screen.fill(BLACK) self.renderer.clear_screen() cell_count = self._count_cells() self.hud.render_sprint_debug(self.screen, self.actual_tps, self.total_ticks, cell_count) pygame.display.flip() self.clock.tick(MAX_FPS) self.last_tick_time = time.perf_counter() def _handle_simulation_ticks(self, tick_interval, deltatime): 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 def _update(self, deltatime): keys = pygame.key.get_pressed() self.input_handler.update_camera(keys, deltatime) def _render(self): self.screen.fill(BLACK) self.renderer.clear_screen() if not self.hud.dragging_splitter: 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.sim_view_rect) self.renderer.render_selected_objects_outline(self.input_handler.selected_objects, self.camera) self.screen.blit(self.sim_view, (self.sim_view_rect.left, self.sim_view_rect.top)) self.hud.manager.draw_ui(self.screen) self.hud.draw_splitters(self.screen) # self.hud.render_mouse_position(self.screen, self.camera, self.sim_view_rect) 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)