import pygame import time import operator from cellular_automaton.cellular_automaton import CellularAutomaton class DisplayFor2D: def __init__(self, grid_rect: list, cellular_automaton: CellularAutomaton, screen): self.grid_size = grid_rect[-2:] self.grid_pos = grid_rect[:2] self._cellular_automaton = cellular_automaton self.screen = screen self.cell_size = self._calculate_cell_display_size() self._surfaces_to_update = [] def set_cellular_automaton(self, cellular_automaton): self._cellular_automaton = cellular_automaton def _redraw_cellular_automaton(self): for cell in self._cellular_automaton.grid.get_cells().values(): self._redraw_cell(cell) pygame.display.update(self._surfaces_to_update) self._surfaces_to_update = [] def _redraw_cell(self, cell): if cell.is_set_for_redraw: cell_color = cell.state.get_state_draw_color(self._cellular_automaton.get_iteration_index()) surface_pos = self._calculate_cell_position(cell) surface_pos = list(map(operator.add, surface_pos, self.grid_pos)) self._surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, self.cell_size))) cell.is_set_for_redraw = False def _calculate_cell_position(self, cell): return list(map(operator.mul, self.cell_size, cell.coordinate)) def _calculate_cell_display_size(self): grid_dimension = self._cellular_automaton.grid.get_dimension() return list(map(operator.truediv, self.grid_size, grid_dimension)) class PyGameFor2D: def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton, ca_iterations_per_draw): self._window_size = windows_size self._cellular_automaton = cellular_automaton self._ca_steps_per_draw = ca_iterations_per_draw pygame.init() pygame.display.set_caption("Cellular Automaton") self._screen = pygame.display.set_mode(self._window_size) self._font = pygame.font.SysFont("monospace", 15) self.ca_display = DisplayFor2D([0, 30, windows_size[0], windows_size[1]-30], cellular_automaton, self._screen) def _print_process_duration(self, time_ca_end, time_ca_start, time_ds_end): self._screen.fill([0, 0, 0], ((0, 0), (self._window_size[0], 30))) self._write_text((10, 5), "CA: " + "{0:.4f}".format(time_ca_end - time_ca_start) + "s") self._write_text((310, 5), "Display: " + "{0:.4f}".format(time_ds_end - time_ca_end) + "s") def _write_text(self, pos, text, color=(0, 255, 0)): label = self._font.render(text, 1, color) update_rect = self._screen.blit(label, pos) pygame.display.update(update_rect) def main_loop(self): running = True while running: time_ca_start = time.time() self._cellular_automaton.evolve_x_times(self._ca_steps_per_draw) time_ca_end = time.time() self.ca_display._redraw_cellular_automaton() time_ds_end = time.time() self._print_process_duration(time_ca_end, time_ca_start, time_ds_end) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False