Skip to content

Commit 5ca4316

Browse files
committed
update copyrights and add conways
1 parent 2e80084 commit 5ca4316

File tree

6 files changed

+219
-0
lines changed

6 files changed

+219
-0
lines changed

Custom_LED_Animations/conways/code.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import board
5+
import neopixel
6+
7+
from conways import ConwaysLifeAnimation
8+
9+
# Update to match the pin connected to your NeoPixels
10+
pixel_pin = board.D10
11+
# Update to match the number of NeoPixels you have connected
12+
pixel_num = 32
13+
14+
# initialize the neopixels. Change out for dotstars if needed.
15+
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.02, auto_write=False)
16+
17+
initial_cells = [
18+
(2, 1),
19+
(3, 1),
20+
(4, 1),
21+
(5, 1),
22+
(6, 1),
23+
]
24+
25+
# initialize the animation
26+
conways = ConwaysLifeAnimation(pixels, 1.0, 0xff00ff, 8, 4, initial_cells)
27+
28+
while True:
29+
# call animation to show the next animation frame
30+
conways.animate()
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
ConwaysLifeAnimation helper class
6+
"""
7+
from micropython import const
8+
9+
from adafruit_led_animation.animation import Animation
10+
from adafruit_led_animation.grid import PixelGrid, HORIZONTAL
11+
import random
12+
13+
14+
class ConwaysLifeAnimation(Animation):
15+
# Constants
16+
DIRECTION_OFFSETS = [
17+
(0, 1),
18+
(0, -1),
19+
(1, 0),
20+
(-1, 0),
21+
(1, 1),
22+
(-1, 1),
23+
(1, -1),
24+
(-1, -1)
25+
]
26+
LIVE = const(0x01)
27+
DEAD = const(0x00)
28+
29+
def __init__(self, pixel_object, speed, color, width, height, initial_cells, equilibrium_restart=True):
30+
"""
31+
Conway's Game of Life implementation. Watch the cells live and die based on the classic rules.
32+
33+
:param pixel_object: The initialised LED object.
34+
:param float speed: Animation refresh rate in seconds, e.g. ``0.1``.
35+
:param color: the color to use for live cells
36+
:param width: the width of the grid
37+
:param height: the height of the grid
38+
:param initial_cells: list of initial cells to be live
39+
:param equilibrium_restart: whether to restart when the simulation gets stuck unchanging
40+
"""
41+
super().__init__(pixel_object, speed, color)
42+
43+
# list to hold which cells are live
44+
self.drawn_pixels = []
45+
46+
# store the initial cells
47+
self.initial_cells = initial_cells
48+
49+
# PixelGrid helper to access the strand as a 2D grid
50+
self.pixel_grid = PixelGrid(pixel_object, width, height, orientation=HORIZONTAL, alternating=False)
51+
52+
# size of the grid
53+
self.width = width
54+
self.height = height
55+
56+
# equilibrium restart boolean
57+
self.equilibrium_restart = equilibrium_restart
58+
59+
# counter to store how many turns since the last change
60+
self.equilibrium_turns = 0
61+
62+
#self._init_cells()
63+
64+
def _is_pixel_off(self, pixel):
65+
return pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0
66+
67+
def _is_grid_empty(self):
68+
"""
69+
Checks if the grid is empty.
70+
71+
:return: True if there are no live cells, False otherwise
72+
"""
73+
for y in range(self.height):
74+
for x in range(self.width):
75+
if not self._is_pixel_off(self.pixel_grid[x,y]):
76+
return False
77+
78+
return True
79+
80+
def _init_cells(self):
81+
"""
82+
Turn off all LEDs then turn on ones cooresponding to the initial_cells
83+
84+
:return: None
85+
"""
86+
self.pixel_grid.fill(0x000000)
87+
for cell in self.initial_cells:
88+
self.pixel_grid[cell] = self.color
89+
90+
def _count_neighbors(self, cell):
91+
"""
92+
Check how many live cell neighbors are found at the given location
93+
:param cell: the location to check
94+
:return: the number of live cell neighbors
95+
"""
96+
neighbors = 0
97+
for direction in ConwaysLifeAnimation.DIRECTION_OFFSETS:
98+
try:
99+
if not self._is_pixel_off(self.pixel_grid[cell[0] + direction[0], cell[1] + direction[1]]):
100+
neighbors += 1
101+
except IndexError:
102+
pass
103+
return neighbors
104+
105+
def draw(self):
106+
"""
107+
draw the current frame of the animation
108+
109+
:return: None
110+
"""
111+
# if there are no live cells
112+
if self._is_grid_empty():
113+
# spawn the inital_cells and return
114+
self._init_cells()
115+
return
116+
117+
# list to hold locations to despawn live cells
118+
despawning_cells = []
119+
120+
# list to hold locations spawn new live cells
121+
spawning_cells = []
122+
123+
# loop over the grid
124+
for y in range(self.height):
125+
for x in range(self.width):
126+
127+
# check and set the current cell type, live or dead
128+
if self._is_pixel_off(self.pixel_grid[x,y]):
129+
cur_cell_type = ConwaysLifeAnimation.DEAD
130+
else:
131+
cur_cell_type = ConwaysLifeAnimation.LIVE
132+
133+
# get a count of the neigbors
134+
neighbors = self._count_neighbors((x, y))
135+
136+
# if the current cell is alive
137+
if cur_cell_type == ConwaysLifeAnimation.LIVE:
138+
# if it has fewer than 2 neighbors
139+
if neighbors < 2:
140+
# add its location to the despawn list
141+
despawning_cells.append((x, y))
142+
143+
# if it has more than 3 neighbors
144+
if neighbors > 3:
145+
# add its location to the despawn list
146+
despawning_cells.append((x, y))
147+
148+
# if the current location is not a living cell
149+
elif cur_cell_type == ConwaysLifeAnimation.DEAD:
150+
# if it has exactly 3 neighbors
151+
if neighbors == 3:
152+
# add the current location to the spawn list
153+
spawning_cells.append((x, y))
154+
155+
# loop over the despawn locations
156+
for cell in despawning_cells:
157+
# turn off LEDs at each location
158+
self.pixel_grid[cell] = 0x000000
159+
160+
# loop over the spawn list
161+
for cell in spawning_cells:
162+
# turn on LEDs at each location
163+
self.pixel_grid[cell] = self.color
164+
165+
# if equilibrium restart mode is enabled
166+
if self.equilibrium_restart:
167+
# if there were no cells spawned or despaned this round
168+
if len(despawning_cells) == 0 and len(spawning_cells) == 0:
169+
# increment equilibrium turns counter
170+
self.equilibrium_turns += 1
171+
# if the counter is 3 or higher
172+
if self.equilibrium_turns >= 3:
173+
# go back to the initial_cells
174+
self._init_cells()
175+
176+
# reset the turns counter to zero
177+
self.equilibrium_turns = 0

Custom_LED_Animations/rainbow_sweep/code.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
14
import board
25
import neopixel
36

Custom_LED_Animations/snake/code.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
14
import board
25
import neopixel
36

Custom_LED_Animations/sweep/code.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
14
import board
25
import neopixel
36

Custom_LED_Animations/zipper/code.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
14
import board
25
import neopixel
36

0 commit comments

Comments
 (0)