Created
June 2, 2013 01:07
-
-
Save Lanny/5692241 to your computer and use it in GitHub Desktop.
A poorly optimized implementation of Conway's Game of Life in Python with PyGame.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
# Conway's game of life | |
# Copyright(c) 2012 Ryan Jenkins | |
import pygame, time | |
from pygame.locals import * | |
class lifeGrid() : | |
def __init__(self, width, height) : | |
self.grid = [] | |
# Populate our grid | |
for col in range(width) : | |
self.grid.append([]) | |
for cell in range(height) : | |
self.grid[-1].append(0) | |
def set(self, value, x, y) : | |
'''Sets cell x, y to value''' | |
self.grid[x][y] = value | |
def toggle(self, x, y) : | |
if self.grid[x][y] : | |
self.grid[x][y] = 0 | |
else : | |
self.grid[x][y] = 1 | |
def get(self, x, y) : | |
'''Return cell state at x,y''' | |
return self.grid[x][y] | |
def birth(self, x, y) : | |
'''Force cell x,y to life''' | |
self.grid[x][y] = 1 | |
def kill(self, x, y) : | |
'''Force cell x,y to death''' | |
self.grid[x][y] = 0 | |
def get_neighbors(self, x, y) : | |
'''Return list of neighbors, live or dead''' | |
possibleNeighbors = [[x+1, y], | |
[x+1, y+1], | |
[x+1, y-1], | |
[x-1, y], | |
[x-1, y+1], | |
[x-1, y-1], | |
[x, y+1], | |
[x, y-1]] | |
trueNeighbors= [] | |
for z in possibleNeighbors : | |
if z[0] == -1 : | |
z[0] = self.get_dims()[0] - 1 | |
elif z[0] == self.get_dims()[0] : | |
z[0] = 0 | |
if z[1] == -1 : | |
z[1] = self.get_dims()[1] - 1 | |
elif z[1] == self.get_dims()[1] : | |
z[1] = 0 | |
trueNeighbors.append(self.grid[z[0]][z[1]]) | |
return trueNeighbors | |
def get_live_neighbors(self, x, y) : | |
'''Return number of living cells adjacent to cell x,y''' | |
live_count = 0 | |
for neighbor in self.get_neighbors(x, y) : | |
if neighbor : live_count += 1 | |
return live_count | |
def get_dims(self) : | |
return (len(self.grid[0]), len(self.grid)) | |
def conways_life(start_grid) : | |
x, y = start_grid.get_dims() | |
new_grid = lifeGrid(x, y) | |
updateRects = [] | |
for mapy in range(y) : | |
for mapx in range(x) : | |
if start_grid.get_live_neighbors(mapx, mapy) < 2 or start_grid.get_live_neighbors(mapx, mapy) > 3 : | |
if start_grid.get(mapx, mapy) : | |
# If we're actually changing the value of the cell, add it | |
# to the list of cells to be re-drawn | |
updateRects.append(coord_to_px(start_grid, mapx, mapy)) | |
new_grid.kill(mapx, mapy) | |
elif start_grid.get_live_neighbors(mapx, mapy) == 3 : | |
if not start_grid.get(mapx, mapy) : | |
updateRects.append(coord_to_px(start_grid, mapx, mapy)) | |
new_grid.birth(mapx, mapy) | |
else : | |
new_grid.set(start_grid.get(mapx, mapy), mapx, mapy) | |
return (new_grid, updateRects) | |
def px_to_coord(grid, x, y) : | |
gridx = x / 10 | |
gridy = -((y / 10)-grid.get_dims()[1]+1) | |
print gridx, gridy | |
return (gridx, gridy) | |
def coord_to_px(grid, x, y) : | |
mapy = (grid.get_dims()[1] - 1 - y) * 10 | |
mapx = (x) * 10 | |
#print mapx, mapy | |
return pygame.Rect(mapx, mapy, 9, 9) | |
def renderGrid(screen, grid) : | |
# Blit the background | |
screen.blit(background, (0,0)) | |
# Draw our cells | |
for gridy in range(grid.get_dims()[1]) : | |
mapy = (grid.get_dims()[1] - 1 - gridy) * 10 | |
for gridx in range(grid.get_dims()[0]) : | |
mapx = gridx * 10 | |
if grid.get(gridx, gridy) : | |
pygame.draw.rect(screen, LIVE_COLOR, (mapx, mapy, 9, 9)) | |
elif not grid.get(gridx, gridy) : | |
pygame.draw.rect(screen, DEAD_COLOR, (mapx, mapy, 9, 9)) | |
if __name__ == '__main__' : | |
WINDOW_SIZE = (600,600) | |
BACKGROUND_COLOR = (0, 0, 0) | |
DEAD_COLOR = (50, 50, 50) | |
LIVE_COLOR = (255, 255, 0) | |
# Pygame ceremony. | |
pygame.init() | |
screen = pygame.display.set_mode(WINDOW_SIZE) | |
background = pygame.Surface(screen.get_size()) | |
background = background.convert() | |
background.fill(BACKGROUND_COLOR) | |
grid = lifeGrid(60, 60) | |
''' | |
grid.birth(56,57); | |
grid.birth(57,56); | |
grid.birth(55,55);grid.birth(56,55);grid.birth(57,55); | |
''' | |
running = True | |
accept_input = True | |
updateRects = [] | |
generation = 0 | |
# Primary event loop. The important stuff goes on here. | |
while running: | |
# Get our event. Prosessing one at a time because of the nature of our game, | |
# we don't need to consider the possibility of simultanious input. | |
event = pygame.event.poll() | |
if event.type == pygame.QUIT: | |
running = False | |
if accept_input : | |
# Go through and figure out what to do with the input | |
if event.type == KEYDOWN : | |
if event.key == 13 : | |
accept_input = False | |
elif event.type == MOUSEBUTTONDOWN : | |
x,y = event.pos | |
gx,gy = px_to_coord(grid,x,y) | |
grid.toggle(gx,gy) | |
renderGrid(screen, grid) | |
pygame.display.update() | |
else : | |
oldRects = updateRects | |
grid, updateRects = conways_life(grid) | |
renderGrid(screen, grid) | |
if generation == 0 : | |
# On first gen, update the whole damn thing | |
pygame.display.update() | |
# And finally update everything added to updateRects that needs to be | |
# drawn to the screen | |
updateRects.extend(oldRects) | |
pygame.display.update()#updateRects) | |
generation += 1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment