Skip to content
Permalink
951ec8a99e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
331 lines (261 sloc) 9.04 KB
# Extension of game code by Nick Jarvis and Nick Wayne
# https://www.pygame.org/project-John+Conway's+Game+of+Life-2899-.html
'''
Conway Composer by Darius Smith
Uses Conway's Game of Life to send OSC messages to another program (PureData)
to generate music
Required libraries
pip3 install osc4py3, pygame
================================================================================
Rules (from Conway's Game of Life)
1) Any live cell with fewer than two live neighbours dies, as if by underpopulation.
2) Any live cell with two or three live neighbours lives on to the next generation.
3) Any live cell with more than three live neighbours dies, as if by overpopulation.
4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
================================================================================
TO PLAY (KEY MAPPINGS)
LEFT CLICK >> mark a cell as 'alive' (blue)
RIGHT CLICK >> mark a cell as 'dead' (black)
- KEY >> clear grid
= KEY >> random grid
a-z or A-Z >> assign a letter to the cell your mouse is over (
UP ARROW - progress time 1 frame
SPACEBAR - starts and stops the progression of time (toggle)
================================================================================
When a cell is "born" (transitions from dead to alive) if it contains a letter
it sends out an OSC message "/conway/<letter>" which can be used to trigger
sounds/events in another program (PureData)
'''
from math import ceil
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
from collections import OrderedDict
import pygame,random
from pygame.locals import *
# Start the system.
osc_startup()
# Make client channels to send packets.
osc_udp_client("127.0.0.1", 8000, "pureData")
pygame.init()
''' ###### PARAMETERS ####### '''
speed = 10 # how many iterations per second
squares = 2 # size of squares: 0 = 8X8, 1 = 16X16, 2 = 32X32, 3 = 64X64
map_size = 32 # the width and height
''' ######################### '''
if squares == 0:
imgs = ["res/alive_8.png","res/dead_8.png",8]
if squares == 1:
imgs = ["res/alive_16.png","res/dead_16.png",16]
if squares == 2:
imgs = ["res/alive_32.png","res/dead_32.png",32]
if squares == 3:
imgs = ["res/alive_64.png","res/dead_64.png",64]
#-----CONFIG-----
width = map_size*imgs[2]
height = map_size*imgs[2]
screen_size = width,height
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
alive = pygame.image.load(imgs[0]).convert()
dead = pygame.image.load(imgs[1]).convert()
done = False
marked_alive = []
font = pygame.font.Font('freesansbold.ttf', 12)
white = (255, 255, 255)
class cell:
def __init__(self,location,alive = False):
self.to_be = None
self.alive = alive
self.pressed = False
self.location = location
self.osc = ''
self.text = font.render('', True, white)
class board:
def __init__(self):
self.map = []
def fill(self,ran):
for i in range(map_size):
self.map.append([])
for g in range(map_size):
if ran == True:
a = random.randint(0,4)
if a == 0: self.map[i].insert(g,cell((i,g),True))
else: self.map[i].insert(g,cell((i,g)))
else: self.map[i].insert(g,cell((i,g)))
def draw(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
loc = cell.location
if cell.alive == True:
screen.blit(alive,(loc[0]*imgs[2],loc[1]*imgs[2]))
else:
screen.blit(dead,(loc[0]*imgs[2],loc[1]*imgs[2]))
def get_cells(self,cell):# gets the cells around a cell
mapa = self.map
a = []
b = []
c = 0
cell_loc = cell.location
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0])][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1])].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1])].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1]+1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0])][abs(cell_loc[1]+1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1]+1)].location)
except Exception: pass
num = len(list(OrderedDict.fromkeys(a)))# removes duplicates
for i in range(len(a)): b.append(mapa[a[i][0]][a[i][1]].alive)
for i in b:# c houses how many cells are alive around it
if i == True: c+=1
if cell.alive == True: # rules
if c < 2: cell.to_be = False
if c > 3:cell.to_be = False
else:
if c == 3: cell.to_be = True
# rules
def update_frame(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
self.get_cells(cell)
def update(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
loc = cell.location
if cell.to_be != None: cell.alive = cell.to_be
if self.map[i][g].alive == True:
screen.blit(alive,(loc[0]*imgs[2],loc[1]*imgs[2]))
textRect = cell.text.get_rect()
textRect.center = (loc[0]*imgs[2] +ceil(imgs[2]/2),loc[1]*imgs[2]+ceil(imgs[2]/2))
screen.blit(cell.text, textRect)
if run and loc not in marked_alive:
# OSC
if cell.osc != '':
print(cell.osc)
# Build a message with autodetection of data types, and send it.
msg = oscbuildparse.OSCMessage("/conway", None, [cell.osc])
osc_send(msg, "pureData")
osc_process()
marked_alive.append(loc)
else:
screen.blit(dead,(loc[0]*imgs[2],loc[1]*imgs[2]))
textRect = cell.text.get_rect()
textRect.center = (loc[0]*imgs[2] +ceil(imgs[2]/2),loc[1]*imgs[2]+ceil(imgs[2]/2))
screen.blit(cell.text, textRect)
if loc in marked_alive:
marked_alive.remove(loc)
cell.to_be = None
def cell_list():
lst = []
for i in range(map_size):
lst.append([])
for g in range(map_size): lst[i].append((board.map[i][g].location[0]*imgs[2],board.map[i][g].location[1]*imgs[2]))
return lst
#############################################################################################
board = board()
board.fill(False)
board.draw()
tp = 0
run = False
shift = False
while done == False:
milliseconds = clock.tick(60)
seconds = milliseconds / 1000.0
tp += milliseconds
for event in pygame.event.get():
if event.type == QUIT:
osc_terminate()
done = True
if event.type == KEYDOWN:
if event.key == K_SPACE:
run = not run
elif event.key == K_MINUS:
board.map = []
board.fill(False)
board.draw()
elif event.key == K_EQUALS:
board.map = []
board.fill(True)
board.draw()
elif event.key == K_RSHIFT or event.key == K_LSHIFT:
shift = True
elif event.key == K_BACKSPACE:
pos = pygame.mouse.get_pos()
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2]:
#print(i,g,key)
board.map[i][g].osc = ''
board.map[i][g].text = font.render('', True, white)
board.update()
else:
key = pygame.key.name(event.key)
if shift:
key = key.upper()
if key.isalpha() and len(key) == 1:
pos = pygame.mouse.get_pos()
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2]:
#print(i,g,key)
board.map[i][g].osc = key
board.map[i][g].text = font.render(key, True, white)
board.update()
if event.type == KEYUP:
if event.key == K_UP:
run = True
board.update_frame()
board.update()
run = False
elif event.key == K_RSHIFT or event.key == K_LSHIFT:
shift = False
if event.type == MOUSEBUTTONUP:
for i in range(map_size):
for g in range(map_size):
board.map[i][g].pressed = False
pressed = pygame.key.get_pressed()
mouse = pygame.mouse.get_pressed()
pos = pygame.mouse.get_pos()
# if pressed[K_MINUS]:
# board.map = []
# board.fill(False)
# board.draw()
# if pressed[K_EQUALS]:
# board.map = []
# board.fill(True)
# board.draw()
if run == True and tp >= 1000/speed :
tp = 0
board.update_frame()
board.update()
if mouse[0]:# makes cells alive
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2] and board.map[i][g].pressed == False:
board.map[i][g].alive = True
board.map[i][g].pressed = True
board.update()
if mouse[2]: # kills cells
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2] and board.map[i][g].pressed == False:
board.map[i][g].alive = False
board.map[i][g].pressed = False
board.update()
pygame.display.flip()
pygame.quit()