performance boost
This commit is contained in:
parent
1042c2ae34
commit
b661d6e060
@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import pygame
|
|
||||||
import random
|
import random
|
||||||
import time
|
|
||||||
|
|
||||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
from cellular_automaton.cellular_automaton import CellularAutomaton
|
||||||
from cellular_automaton.ca_rule import Rule
|
from cellular_automaton.ca_rule import Rule
|
||||||
@ -11,75 +9,9 @@ from cellular_automaton.ca_display import PyGameFor2D
|
|||||||
from cellular_automaton.ca_cell_state import CellState
|
from cellular_automaton.ca_cell_state import CellState
|
||||||
|
|
||||||
|
|
||||||
class WorldGeneratorWindow:
|
|
||||||
def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton):
|
|
||||||
self.window_size = windows_size
|
|
||||||
self.grid_size = self.window_size.copy()
|
|
||||||
self.grid_size[1] -= 20
|
|
||||||
|
|
||||||
pygame.init()
|
|
||||||
pygame.display.set_caption("World Generator")
|
|
||||||
self.screen = pygame.display.set_mode(self.window_size)
|
|
||||||
|
|
||||||
self._cellular_automaton = cellular_automaton
|
|
||||||
self.font = pygame.font.SysFont("monospace", 15)
|
|
||||||
|
|
||||||
def set_cellular_automaton(self, cellular_automaton):
|
|
||||||
self._cellular_automaton = cellular_automaton
|
|
||||||
|
|
||||||
def _display_cellular_automaton(self):
|
|
||||||
grid_dimension = self._cellular_automaton.grid.get_dimension()
|
|
||||||
|
|
||||||
cell_size = [x / y for x, y in zip(self.grid_size, grid_dimension)]
|
|
||||||
|
|
||||||
surfaces_to_update = []
|
|
||||||
for cell in self._cellular_automaton.grid.get_cells().values():
|
|
||||||
if not cell.is_set_for_redrawing():
|
|
||||||
continue
|
|
||||||
cell_coordinate = cell.coordinate
|
|
||||||
status = cell.get_status_for_iteration(self._cellular_automaton.get_iteration_index())
|
|
||||||
if status is None:
|
|
||||||
status = [0]
|
|
||||||
red = 0
|
|
||||||
if status[0] >= 10:
|
|
||||||
red = 255
|
|
||||||
cell_color = [red, 0, 0]
|
|
||||||
surface_pos = [x * y for x, y in zip(cell_size, cell_coordinate)]
|
|
||||||
surface_pos[1] += 20
|
|
||||||
surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, cell_size)))
|
|
||||||
cell.release_from_redraw()
|
|
||||||
pygame.display.update(surfaces_to_update)
|
|
||||||
|
|
||||||
def main_loop(self):
|
|
||||||
running = True
|
|
||||||
|
|
||||||
while running:
|
|
||||||
time_ca_start = time.time()
|
|
||||||
self._cellular_automaton.evolve_x_times(10)
|
|
||||||
time_ca_end = time.time()
|
|
||||||
self._display_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
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
class TestRule(Rule):
|
class TestRule(Rule):
|
||||||
def evolve_cell(self, cell, neighbors, iteration_index):
|
def evolve_cell(self, cell, neighbors, iteration_index):
|
||||||
active = False
|
active = False
|
||||||
last_iteration = iteration_index - 1
|
|
||||||
if cell.state is None:
|
if cell.state is None:
|
||||||
rand = random.randrange(0, 101, 1)
|
rand = random.randrange(0, 101, 1)
|
||||||
if rand <= 99:
|
if rand <= 99:
|
||||||
@ -89,8 +21,8 @@ class TestRule(Rule):
|
|||||||
cell.set_for_redraw()
|
cell.set_for_redraw()
|
||||||
active = True
|
active = True
|
||||||
elif len(neighbors) == 8:
|
elif len(neighbors) == 8:
|
||||||
left_neighbour_status = neighbors[3].state.get_status_of_iteration(last_iteration)
|
left_neighbour_state = neighbors[3].state.get_status_of_iteration(iteration_index - 1)
|
||||||
active = cell.state.set_status_of_iteration(left_neighbour_status, iteration_index)
|
active = cell.state.set_status_of_iteration(left_neighbour_state, iteration_index)
|
||||||
if active:
|
if active:
|
||||||
cell.set_for_redraw()
|
cell.set_for_redraw()
|
||||||
return active
|
return active
|
||||||
@ -108,7 +40,8 @@ class MyStatus(CellState):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
random.seed(1000)
|
||||||
rule = TestRule()
|
rule = TestRule()
|
||||||
ca = CellularAutomaton([400, 400], MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), rule)
|
ca = CellularAutomaton([500, 500], MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), rule)
|
||||||
ca_window = PyGameFor2D([1000, 730], ca)
|
ca_window = PyGameFor2D([1000, 730], ca)
|
||||||
ca_window.main_loop()
|
ca_window.main_loop()
|
||||||
|
@ -20,3 +20,6 @@ class Cell:
|
|||||||
|
|
||||||
def release_from_redraw(self):
|
def release_from_redraw(self):
|
||||||
self._dirty = False
|
self._dirty = False
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
@ -31,19 +31,11 @@ class Grid:
|
|||||||
:param cells: A list of Cell objects, that shall be considered in the next evolution cycle.
|
:param cells: A list of Cell objects, that shall be considered in the next evolution cycle.
|
||||||
"""
|
"""
|
||||||
for cell in cells:
|
for cell in cells:
|
||||||
self._active_cells[cell.name] = cells
|
self._active_cells[cell.name] = cell
|
||||||
|
|
||||||
def get_cell_and_neighbors(self, cell_name):
|
def get_cell_and_neighbors(self, cell_name):
|
||||||
cell = self._cells[cell_name]
|
cell = self._cells[cell_name]
|
||||||
neighbours = cell.neighbours
|
return [cell, cell.neighbours]
|
||||||
neighbour_objects = []
|
|
||||||
for ne in neighbours:
|
|
||||||
neighbour_objects.append(self._cells[ne])
|
|
||||||
|
|
||||||
return [cell, neighbour_objects]
|
|
||||||
|
|
||||||
def get_cell_by_coordinate(self, coordinate):
|
|
||||||
return self._cells[_join_coordinate(coordinate)]
|
|
||||||
|
|
||||||
def get_dimension(self):
|
def get_dimension(self):
|
||||||
return self._dimension
|
return self._dimension
|
||||||
@ -76,20 +68,14 @@ class Grid:
|
|||||||
new_cod = coordinate + [cell_index]
|
new_cod = coordinate + [cell_index]
|
||||||
recursion_method(dimension_index + 1, new_cod)
|
recursion_method(dimension_index + 1, new_cod)
|
||||||
|
|
||||||
def _set_cell_neighbours(self, dimension_index=0, coordinate=None):
|
def _set_cell_neighbours(self):
|
||||||
""" Recursively steps down the dimensions to get the string instances for each cells neighbours.
|
for cell in self._cells.values():
|
||||||
:param dimension_index: The index indicating which dimension is currently traversed.
|
neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate,
|
||||||
:param coordinate: The coordinate generated so far.
|
self._dimension)
|
||||||
(each recursion adds one dimension to the coordinate.
|
cell.set_neighbours(list(map(self._get_cell_by_coordinate, neighbours_coordinates)))
|
||||||
"""
|
|
||||||
coordinate = _instantiate_coordinate_if_necessary(coordinate)
|
|
||||||
|
|
||||||
try:
|
def _get_cell_by_coordinate(self, coordinate):
|
||||||
self._recursive_step_down_dimensions(coordinate.copy(), dimension_index, self._set_cell_neighbours)
|
return self._cells[_join_coordinate(coordinate)]
|
||||||
except IndexError:
|
|
||||||
neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(coordinate, self._dimension)
|
|
||||||
neighbour_names = [self._cells[_join_coordinate(nc)].name for nc in neighbours_coordinates]
|
|
||||||
self._cells[_join_coordinate(coordinate)].set_neighbours(neighbour_names)
|
|
||||||
|
|
||||||
|
|
||||||
def _instantiate_coordinate_if_necessary(coordinate):
|
def _instantiate_coordinate_if_necessary(coordinate):
|
||||||
|
@ -46,17 +46,16 @@ class CellularAutomaton:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _evolve_all_active_cells(self):
|
def _evolve_all_active_cells(self):
|
||||||
active_cells = self.grid.get_active_cell_names()
|
active_cells = self.grid.get_active_cells()
|
||||||
self.grid.clear_active_cells()
|
self.grid.clear_active_cells()
|
||||||
self._evolve_cells(active_cells)
|
self._evolve_cells(active_cells.values())
|
||||||
|
|
||||||
def _is_evolution_finished(self):
|
def _is_evolution_finished(self):
|
||||||
return len(self.grid.get_active_cell_names()) == 0
|
return len(self.grid.get_active_cell_names()) == 0
|
||||||
|
|
||||||
def _evolve_cells(self, cell_names: list):
|
def _evolve_cells(self, cells: list):
|
||||||
for cell_name in cell_names:
|
for cell in cells:
|
||||||
cell_info = self.grid.get_cell_and_neighbors(cell_name)
|
active = self.evolution_rule.evolve_cell(cell, cell.neighbours, self.iteration)
|
||||||
active = self.evolution_rule.evolve_cell(cell_info[0], cell_info[1], self.iteration)
|
|
||||||
|
|
||||||
if active:
|
if active:
|
||||||
self.grid.set_cells_active([cell_info[0]] + cell_info[1])
|
self.grid.set_cells_active([cell] + cell.neighbours)
|
||||||
|
Loading…
Reference in New Issue
Block a user