diff --git a/design.py b/design.py index 5826e72..f5e2a5e 100644 --- a/design.py +++ b/design.py @@ -32,6 +32,6 @@ def setupUi(self, MainWindow): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "Conwell\'s Game of Life")) + MainWindow.setWindowTitle(_translate("MainWindow", "Conway\'s Game of Life")) from universeview import UniverseView diff --git a/design.ui b/design.ui index 0243f85..9980d8f 100644 --- a/design.ui +++ b/design.ui @@ -11,7 +11,7 @@ - Conwell's Game of Life + Conway's Game of Life 0.950000000000000 diff --git a/gif.sh b/gif.sh new file mode 100755 index 0000000..5b63281 --- /dev/null +++ b/gif.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# This script assumes imagemagick is installed +# and converts the latest generated +lastfolder=$(ls 'recordings' | tail -n 1) +cd "recordings/$lastfolder" +convert -delay 20 -loop 0 *png animation.gif diff --git a/life.py b/life.py index b501e0a..5173f65 100644 --- a/life.py +++ b/life.py @@ -7,7 +7,7 @@ class LifeformState(Enum): resurrecting = 3 class Lifeform(): - def __init__(self, state=False): + def __init__(self, c1, c2, state=False): ''' Create a lifeform :param state: True stands for alive, False stands for dead. @@ -15,6 +15,9 @@ def __init__(self, state=False): self._age = 0 self._state = LifeformState.alive if state else LifeformState.dead self._neighbors = [] + self._c1 = c1 + self._c2 = c2 + def alive(self): ''' @@ -46,9 +49,9 @@ def play(self): if self.alive(): self._age += 1 - if (nc < 2 or nc > 3) and self.alive(): + if (nc < self._c1 or nc > self._c2) and self.alive(): self._state = LifeformState.dying - if nc == 3 and not self.alive(): + if nc == self._c2 and not self.alive(): self._state = LifeformState.resurrecting def updateState(self): @@ -62,4 +65,4 @@ def kill(self): self._state = LifeformState.dead def resurrect(self): - self._state = LifeformState.alive \ No newline at end of file + self._state = LifeformState.alive diff --git a/universe.py b/universe.py index 8622e11..8206a96 100644 --- a/universe.py +++ b/universe.py @@ -1,17 +1,19 @@ from life import * class Universe(): - def __init__(self, state): + def __init__(self, state, c1 = 2, c2 = 3): ''' Initialize the game with the initial state (the only input to the original Game of Life) :param state: 2D list of booleans ''' self._age = 0 + self._c1 = c1 + self._c2 = c2 self.seed(state) def seed(self, state): # create all the Lifeforms and store them into the Universe's state - self._state = [[Lifeform(i) for i in row] for row in state] # 2D list of Lifeforms + self._state = [[Lifeform(self._c1, self._c2, i) for i in row] for row in state] # 2D list of Lifeforms self.updateNeighbors() def getNeighbors(self, col, row): diff --git a/universeview.py b/universeview.py index 23cfff6..fef2754 100644 --- a/universeview.py +++ b/universeview.py @@ -1,8 +1,9 @@ -from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsRectItem +from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsRectItem, QWidget from PyQt5.QtCore import Qt, QTimer, QRectF from PyQt5.QtGui import QBrush, QPen, QColor from universe import Universe -from time import perf_counter +from time import perf_counter, strftime, gmtime +import os class constants(): DefaultCellToScreenRatio = 0.005 @@ -33,6 +34,7 @@ def __init__(self, parent=None): self._showGrid = False self._mousePosition = (0,0) self._CellToScreenRatio = 0.01 + self._recording = False def initialize(self, initialState): self.universe = Universe(initialState) @@ -126,14 +128,18 @@ def status(self): age.setDefaultTextColor(Qt.white) age.setPos(0, 30) - age = self._scene.addText('Mouse at x {}, y {}'.format(self._mousePosition[0], self._mousePosition[1])) + age = self._scene.addText('Mouse at: {}, {}'.format(self._mousePosition[0], self._mousePosition[1])) age.setDefaultTextColor(Qt.white) age.setPos(0, 45) - age = self._scene.addText('Universe size {}x{}'.format(self.rows, self.cols)) + age = self._scene.addText('Universe size {}, {}'.format(self.rows, self.cols)) age.setDefaultTextColor(Qt.white) age.setPos(0, 60) + age = self._scene.addText('Recording: {}'.format(self._recording)) + age.setDefaultTextColor(Qt.white) + age.setPos(0, 75) + def drawGrid(self): for row in range(self.rows - 1): line = self._scene.addLine(0, (row + 1) * self.cell_size, self._scene.width(), (row + 1) * self.cell_size) @@ -174,6 +180,10 @@ def timeTick(self): # evolve self.universe.evolve() + if self._recording: + pixMap = QWidget.grab(self) + pixMap.save("{}/{}.png".format(self._recordingDir, str(self.universe._age).zfill(5))) + def keyPressEvent(self, QKeyEvent): if QKeyEvent.key() == Qt.Key_Space: if self._timer.isActive(): @@ -187,6 +197,18 @@ def keyPressEvent(self, QKeyEvent): elif QKeyEvent.key() == Qt.Key_G: self._showGrid = not self._showGrid + elif QKeyEvent.key() == Qt.Key_R: + if not os.path.exists('recordings'): + os.makedirs('recordings') + if not self._recording: + dir = strftime("recordings/%Y-%m-%d %H:%M:%S", gmtime()) + if not os.path.exists(dir): + os.makedirs(dir) + self._recordingDir = dir + self._recording = True + else: + self._recording = False + elif QKeyEvent.key() == Qt.Key_Minus: self._timerTickPeriod *= 1.05 self._timer.setInterval(self._timerTickPeriod * 1000)