neuropercolation/cellular_automaton/display.py

77 lines
3.4 KiB
Python
Raw Normal View History

2018-12-09 10:20:16 +00:00
import pygame
import time
import operator
2019-02-17 10:11:27 +00:00
from . import CellularAutomatonState, CellularAutomatonProcessor
2018-12-09 10:20:16 +00:00
2019-01-05 16:38:21 +00:00
class _DisplayInfo:
def __init__(self, grid_size, grid_pos, cell_size, screen):
self.grid_size = grid_size
self.grid_pos = grid_pos
self.cell_size = cell_size
2018-12-09 10:20:16 +00:00
self.screen = screen
2019-01-05 16:38:21 +00:00
class DisplayFor2D:
2019-02-16 17:05:26 +00:00
def __init__(self, grid_rect: list, cellular_automaton: CellularAutomatonState, screen):
2019-01-05 16:38:21 +00:00
self._cellular_automaton = cellular_automaton
cell_size = self._calculate_cell_display_size(grid_rect[-2:])
self._display_info = _DisplayInfo(grid_rect[-2:], grid_rect[:2], cell_size, screen)
2018-12-09 10:20:16 +00:00
def redraw_cellular_automaton(self):
update_rects = list(self._cell_redraw_rectangles())
pygame.display.update(update_rects)
def _cell_redraw_rectangles(self):
for coordinate, cell in self._cellular_automaton.cells.items():
if cell.state.is_set_for_redraw():
2019-02-16 17:05:26 +00:00
cell_color = cell.state.get_state_draw_color(self._cellular_automaton.current_evolution_step)
cell_pos = self._calculate_cell_position(self._display_info.cell_size, coordinate)
surface_pos = list(map(operator.add, cell_pos, self._display_info.grid_pos))
yield self._display_info.screen.fill(cell_color, (surface_pos, self._display_info.cell_size))
cell.state.was_redrawn()
2018-12-09 10:20:16 +00:00
2019-01-05 16:38:21 +00:00
def _calculate_cell_display_size(self, grid_size):
grid_dimension = self._cellular_automaton.dimension
2019-01-05 16:38:21 +00:00
return list(map(operator.truediv, grid_size, grid_dimension))
2018-12-09 10:20:16 +00:00
2019-02-16 17:05:26 +00:00
@staticmethod
def _calculate_cell_position(cell_size, coordinate):
return list(map(operator.mul, cell_size, coordinate))
2018-12-09 10:20:16 +00:00
class PyGameFor2D:
2019-02-16 17:05:26 +00:00
def __init__(self, window_size: list, cellular_automaton: CellularAutomatonState):
self._window_size = window_size
2018-12-09 10:20:16 +00:00
self._cellular_automaton = cellular_automaton
pygame.init()
pygame.display.set_caption("Cellular Automaton")
2019-01-05 14:12:07 +00:00
self._screen = pygame.display.set_mode(self._window_size)
self._font = pygame.font.SysFont("monospace", 15)
2018-12-09 10:20:16 +00:00
self.ca_display = DisplayFor2D([0, 30, window_size[0], window_size[1] - 30], cellular_automaton, self._screen)
2018-12-09 10:20:16 +00:00
def _print_process_duration(self, time_ca_end, time_ca_start, time_ds_end):
2019-01-05 14:12:07 +00:00
self._screen.fill([0, 0, 0], ((0, 0), (self._window_size[0], 30)))
2018-12-09 10:20:16 +00:00
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")
2019-02-17 10:17:20 +00:00
self._write_text((660, 5), "Step: " + str(self._cellular_automaton.current_evolution_step))
2018-12-09 10:20:16 +00:00
def _write_text(self, pos, text, color=(0, 255, 0)):
2019-01-05 14:12:07 +00:00
label = self._font.render(text, 1, color)
update_rect = self._screen.blit(label, pos)
2018-12-09 10:20:16 +00:00
pygame.display.update(update_rect)
2019-02-16 17:05:26 +00:00
def main_loop(self, cellular_automaton_processor: CellularAutomatonProcessor, evolution_steps_per_draw):
2018-12-09 10:20:16 +00:00
running = True
2019-02-09 17:16:19 +00:00
2018-12-09 10:20:16 +00:00
while running:
pygame.event.get()
2018-12-09 10:20:16 +00:00
time_ca_start = time.time()
2019-02-17 10:17:20 +00:00
cellular_automaton_processor.evolve_x_times(evolution_steps_per_draw)
2018-12-09 10:20:16 +00:00
time_ca_end = time.time()
self.ca_display.redraw_cellular_automaton()
2018-12-09 10:20:16 +00:00
time_ds_end = time.time()
self._print_process_duration(time_ca_end, time_ca_start, time_ds_end)