139 lines
3.7 KiB
Python
Executable File
139 lines
3.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
## The Game of Life using pyglet. A quite slow implementation.
|
|
|
|
import pyglet
|
|
from pyglet.window import key
|
|
import numpy
|
|
|
|
|
|
class Application(pyglet.window.Window):
|
|
|
|
def __init__(self):
|
|
"""Window initialization"""
|
|
super().__init__(caption="The Game of Life", resizable=True)
|
|
self.size = 10
|
|
self.cells = numpy.zeros((self.width // self.size,
|
|
self.height // self.size))
|
|
self.running = False
|
|
self.full = False
|
|
self.frequency = 1 / 120
|
|
pyglet.gl.glClearColor(0, 0.13, 0.16, 1.0)
|
|
|
|
def on_mouse_press(self, x, y, button, modifiers):
|
|
"""Turn alive the cell under the pointer"""
|
|
value = False if modifiers == key.MOD_COMMAND else True
|
|
if x >= 0 and y >= 0:
|
|
try:
|
|
self.cells[x // self.size][y // self.size] = value
|
|
except IndexError:
|
|
pass
|
|
|
|
def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
|
|
"""Turn cells alive while dragging"""
|
|
self.on_mouse_press(x, y, button, modifiers)
|
|
|
|
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
|
|
self.size += scroll_y
|
|
if self.size == 0:
|
|
self.size += 1
|
|
self.resize_space()
|
|
|
|
def on_key_press(self, button, modifiers):
|
|
# Toggle update
|
|
if button == key.SPACE:
|
|
if self.running:
|
|
pyglet.clock.unschedule(self.update)
|
|
self.running = False
|
|
else:
|
|
pyglet.clock.schedule_interval(self.update, self.frequency)
|
|
self.running = True
|
|
# Reset space
|
|
elif button == key.BACKSPACE:
|
|
self.cells.fill(0)
|
|
# Toggle fullscreen
|
|
elif modifiers == key.MOD_COMMAND and button == key.F:
|
|
if self.fullscreen:
|
|
self.set_fullscreen(False)
|
|
self.full = False
|
|
else:
|
|
self.set_fullscreen()
|
|
self.full = True
|
|
# Change update frequency
|
|
if button == key.SLASH:
|
|
self.frequency += 0.1
|
|
if self.running:
|
|
pyglet.clock.unschedule(self.update)
|
|
pyglet.clock.schedule_interval(self.update, self.frequency)
|
|
elif button == key.BRACKETRIGHT:
|
|
self.frequency -= 0.1
|
|
if self.running:
|
|
pyglet.clock.unschedule(self.update)
|
|
pyglet.clock.schedule_interval(self.update, self.frequency)
|
|
|
|
def on_resize(self, width, height):
|
|
super().on_resize(width, height)
|
|
self.resize_space()
|
|
|
|
def on_draw(self):
|
|
"""Draw the frame"""
|
|
self.clear()
|
|
pyglet.gl.glColor3f(0.15, 0.6, 0.5)
|
|
for x, row in enumerate(self.cells):
|
|
for y, cell in enumerate(row):
|
|
if cell:
|
|
self.draw_cell(x, y)
|
|
if self.size > 7:
|
|
self.draw_grid()
|
|
|
|
def resize_space(self):
|
|
self.cells.resize((self.width // self.size, self.height // self.size))
|
|
|
|
def draw_grid(self):
|
|
"""Draw the grid"""
|
|
pyglet.gl.glColor3f(0.06, 0.17, 0.21)
|
|
for i in range(self.height // self.size):
|
|
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
|
|
('v2i', (0, i * self.size, self.width, i * self.size)))
|
|
for j in range(self.width // self.size):
|
|
pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
|
|
('v2i', (j * self.size, 0, j * self.size, self.height)))
|
|
|
|
def draw_cell(self, x, y):
|
|
"""Draw a square"""
|
|
x, y = x * self.size, y * self.size
|
|
x1, y1, x2, y2 = x, y, x + self.size, y + self.size
|
|
pyglet.graphics.draw(4, pyglet.gl.GL_QUADS,
|
|
('v2f', (x1, y1, x1, y2, x2, y2, x2, y1)))
|
|
|
|
def update(self, dt):
|
|
"""Calculate the next frame"""
|
|
copy = numpy.copy(self.cells)
|
|
for x, row in enumerate(self.cells):
|
|
for y, cell in enumerate(row):
|
|
copy[x][y] = self.alive(x, y)
|
|
self.cells = numpy.copy(copy)
|
|
|
|
def alive(self, x, y):
|
|
"""Calculate if a cell will be alive in the next frame"""
|
|
livings = 0
|
|
for i in (-1, 0, 1):
|
|
for j in (-1, 0, 1):
|
|
try:
|
|
if (self.cells[x + i][y + j]
|
|
and x + i > 0 and y + j > 0):
|
|
livings += 1
|
|
except IndexError:
|
|
continue
|
|
if self.cells[x][y]:
|
|
livings -= 1
|
|
if not self.cells[x][y] and livings == 3:
|
|
return 1
|
|
elif self.cells[x][y] and livings in (2, 3):
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
app = Application()
|
|
pyglet.app.run()
|