Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
13 changed files
with
1,321 additions
and
43 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,331 @@ | ||
# 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() |
BIN
+8 KB
conwayOSC/res/Thumbs.db
Binary file not shown.
BIN
+323 Bytes
conwayOSC/res/alive_16.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+641 Bytes
conwayOSC/res/alive_32.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+1.44 KB
conwayOSC/res/alive_64.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+214 Bytes
conwayOSC/res/alive_8.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+252 Bytes
conwayOSC/res/dead_16.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+435 Bytes
conwayOSC/res/dead_32.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+822 Bytes
conwayOSC/res/dead_64.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN
+203 Bytes
conwayOSC/res/dead_8.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
Oops, something went wrong.