All checks were successful
Build Simulation and Test / Run All Tests (push) Successful in 1m5s
216 lines
8.3 KiB
Python
216 lines
8.3 KiB
Python
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, 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 _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
|
|
|
|
if not self.input_handler.is_paused:
|
|
self._handle_simulation_ticks(tick_interval, deltatime)
|
|
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()
|
|
self.hud.render_sprint_debug(self.screen, self.actual_tps, self.total_ticks)
|
|
pygame.display.flip()
|
|
self.clock.tick(MAX_FPS)
|
|
|
|
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) |