Skip to content

Instantly share code, notes, and snippets.

@bened-h
Created July 8, 2020 04:40
Show Gist options
  • Save bened-h/e44cb5348e6d7c2dd72dea494b04edea to your computer and use it in GitHub Desktop.
Save bened-h/e44cb5348e6d7c2dd72dea494b04edea to your computer and use it in GitHub Desktop.
# blender 2.8
"""
This script implements Convey's "Game of Life" in Blender 2.8
It relies on the blender file containing a mesh called "Cube"
(sidelength = 1) and an empty collection called "Grid".
# original code: https://gist.github.com/bened-h/9d56a03e9a14b917980c1d4039bf1687
# inspired by this comment https://www.reddit.com/r/generative/comments/ghuvlg/i_made_a_25dimensional_version_of_conways_game_of/fqb5nlu/
"""
import bpy
from math import log
from random import random
gridsize = 20 # number of tiles in the grid (x/y-axis)
tile_size = 10./gridsize # the number descirbes grid dimension
time_stretch = 3 # distance between keyframes (iteration steps)
class Tile():
grid = [[None for x in range(gridsize)] for y in range(gridsize)]
stepnr = 1
def __init__(self,x,y):
self.grid[x][y] = self # put the Tile object in the grid array
self.x, self.y = x, y
# make a new object from the default cube:
obj = bpy.data.objects.new("Cube", bpy.data.meshes["Cube"])
obj.location = (x*tile_size,y*tile_size,0)
obj.scale = [tile_size, tile_size, tile_size]
bpy.data.collections["Grid"].objects.link(obj)
self.obj = obj
self.age = 0
self.nextlife = False
def get_neighbors(self):
x, y = self.x, self.y
l = x-1
r = x+1 if x<gridsize-1 else 0
d = y-1
u = y+1 if y<gridsize-1 else 0
g = self.grid
self.neighbors = [g[l][u], g[x][u], g[r][u], g[r][y],
g[r][d], g[x][d], g[l][d], g[l][y]]
def random_life(self):
if random() < .2:
self.nextlife = True
self.update()
def check(self):
sum = len([1 for n in self.neighbors if n.age > 0])
if self.age >0 and (sum < 2 or sum > 3):
self.nextlife = False
elif sum == 3:
self.nextlife = True
def update(self):
if self.nextlife:
if self.age > 0: # staying alive
self.age += 1
else: # is dead >> birth
self.age = 1
# self.obj.location.z = log(self.age +1) * tile_size
self.obj.location.z = (1 - 1/(self.age+1) ) * tile_size * 2
else: # it's dead
if self.age > 0: # it's alive but dies
self.age = 0
else: # it stays dead
self.age -= 1
# self.obj.location.z = -log(abs(self.age)+1) * tile_size
self.obj.location.z = (1 - 1/(abs(self.age)+1) ) * -tile_size * 2
# add a keyframe
self.obj.keyframe_insert(data_path = "location", index = 2, frame = Tile.stepnr * 2)
# delete old tiles
for obj in bpy.data.collections["Grid"].objects:
bpy.data.collections["Grid"].objects.unlink(obj)
# initialize grid of tiles:
tiles = [Tile(x,y) for x in range(gridsize) for y in range(gridsize)]
for t in tiles:
t.random_life()
t.get_neighbors()
# main loop:
iterations = 300
# set timeline length
bpy.context.scene.frame_end = time_stretch*iterations
for i in range(iterations):
for t in tiles: t.check()
for t in tiles: t.update()
Tile.stepnr += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment