Skip to content

Commit b734da7

Browse files
authored
Merge pull request #823 from dastels/flying-toasters
Flying toaster code
2 parents f1da865 + 2b127b0 commit b734da7

2 files changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
"""
2+
Continuously scroll randomly generated After Dark style toasters.
3+
Designed for an ItsyBitsy M4 Express and a 1.3" 240x240 TFT
4+
5+
Adafruit invests time and resources providing this open source code.
6+
Please support Adafruit and open source hardware by purchasing
7+
products from Adafruit!
8+
9+
Written by Dave Astels for Adafruit Industries
10+
Copyright (c) 2019 Adafruit Industries
11+
Licensed under the MIT license.
12+
13+
All text above must be included in any redistribution.
14+
15+
Requires CircuitPython 5.0 or later.
16+
"""
17+
18+
import time
19+
from random import seed, randint
20+
import board
21+
import displayio
22+
from adafruit_st7789 import ST7789
23+
import adafruit_imageload
24+
25+
26+
# Sprite cell values
27+
EMPTY = 0
28+
CELL_1 = EMPTY + 1
29+
CELL_2 = CELL_1 + 1
30+
CELL_3 = CELL_2 + 1
31+
CELL_4 = CELL_3 + 1
32+
TOAST = CELL_4 + 1
33+
34+
NUMBER_OF_SPRITES = TOAST + 1
35+
36+
# Animation support
37+
38+
FIRST_CELL = CELL_1
39+
LAST_CELL = CELL_4
40+
41+
NUMBER_OF_CELLS = (LAST_CELL - FIRST_CELL) + 1
42+
43+
# A boolean array corresponding to the sprites, True if it's part of the animation sequence.
44+
ANIMATED = [_sprite >= FIRST_CELL and _sprite <= LAST_CELL for _sprite in range(NUMBER_OF_SPRITES)]
45+
46+
47+
# The chance (out of 10) that a new toaster, or toast will enter
48+
CHANCE_OF_NEW_TOASTER = 5
49+
CHANCE_OF_NEW_TOAST = 2
50+
51+
# How many sprites to styart with
52+
INITIAL_NUMBER_OF_SPRITES= 5
53+
54+
# Global variables
55+
display = None
56+
tilegrid = None
57+
58+
seed(int(time.monotonic()))
59+
60+
def make_display():
61+
"""Set up the display support.
62+
Return the Display object.
63+
"""
64+
spi = board.SPI()
65+
while not spi.try_lock():
66+
pass
67+
spi.configure(baudrate=24000000) # Configure SPI for 24MHz
68+
spi.unlock()
69+
tft_cs = board.D10
70+
tft_dc = board.D7
71+
72+
displayio.release_displays()
73+
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=board.D9)
74+
75+
return ST7789(display_bus, width=240, height=240, rowstart=80, auto_refresh=True)
76+
77+
def make_tilegrid():
78+
"""Construct and return the tilegrid."""
79+
group = displayio.Group(max_size=10)
80+
81+
sprite_sheet, palette = adafruit_imageload.load("/spritesheet.bmp",
82+
bitmap=displayio.Bitmap,
83+
palette=displayio.Palette)
84+
grid = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
85+
width=9, height=9,
86+
tile_height=32, tile_width=32,
87+
x=0, y=-32,
88+
default_tile=EMPTY)
89+
group.append(grid)
90+
display.show(group)
91+
return grid
92+
93+
def random_cell():
94+
return randint(FIRST_CELL, LAST_CELL)
95+
96+
def evaluate_position(row, col):
97+
"""Return whether how long of aa toaster is placable at the given location.
98+
:param row: the tile row (0-9)
99+
:param col: the tile column (0-9)
100+
"""
101+
return tilegrid[col, row] == EMPTY
102+
103+
def seed_toasters(number_of_toasters):
104+
"""Create the initial toasters so it doesn't start empty"""
105+
for _ in range(number_of_toasters):
106+
while True:
107+
row = randint(0, 8)
108+
col = randint(0, 8)
109+
if evaluate_position(row, col):
110+
break
111+
tilegrid[col, row] = random_cell()
112+
113+
def next_sprite(sprite):
114+
if ANIMATED[sprite]:
115+
return (((sprite - FIRST_CELL) + 1) % NUMBER_OF_CELLS) + FIRST_CELL
116+
return sprite
117+
118+
def advance_animation():
119+
"""Cycle through animation cells each time."""
120+
for tile_number in range(81):
121+
tilegrid[tile_number] = next_sprite(tilegrid[tile_number])
122+
123+
def slide_tiles():
124+
"""Move the tilegrid one pixel to the bottom-left."""
125+
tilegrid.x -= 1
126+
tilegrid.y += 1
127+
128+
def shift_tiles():
129+
"""Move tiles one spot to the left, and reset the tilegrid's position"""
130+
for row in range(8, 0, -1):
131+
for col in range(8):
132+
tilegrid[col, row] = tilegrid[col + 1, row - 1]
133+
tilegrid[8, row] = EMPTY
134+
for col in range(9):
135+
tilegrid[col, 0] = EMPTY
136+
tilegrid.x = 0
137+
tilegrid.y = -32
138+
139+
def get_entry_row():
140+
while True:
141+
row = randint(0, 8)
142+
if tilegrid[8, row] == EMPTY and tilegrid[7, row] == EMPTY:
143+
return row
144+
145+
def get_entry_column():
146+
while True:
147+
col = randint(0, 8)
148+
if tilegrid[col, 0] == EMPTY and tilegrid[col, 1] == EMPTY:
149+
return col
150+
151+
def add_toaster_or_toast():
152+
"""Maybe add a new toaster or toast on the right and/or top at a randon open location"""
153+
if randint(1, 10) <= CHANCE_OF_NEW_TOAST:
154+
tile = TOAST
155+
elif randint(1, 10) <= CHANCE_OF_NEW_TOASTER:
156+
tile = random_cell()
157+
else:
158+
tile = EMPTY
159+
tilegrid[8, get_entry_row()] = tile
160+
161+
if randint(1, 10) <= CHANCE_OF_NEW_TOAST:
162+
tile = TOAST
163+
elif randint(1, 8) <= CHANCE_OF_NEW_TOASTER:
164+
tile = random_cell()
165+
else:
166+
tile = EMPTY
167+
tilegrid[get_entry_column(), 0] = tile
168+
169+
display = make_display()
170+
tilegrid = make_tilegrid()
171+
seed_toasters(INITIAL_NUMBER_OF_SPRITES)
172+
display.refresh()
173+
174+
while True:
175+
for _ in range(32):
176+
display.refresh(target_frames_per_second=80)
177+
advance_animation()
178+
slide_tiles()
179+
shift_tiles()
180+
add_toaster_or_toast()
181+
display.refresh(target_frames_per_second=120)
9.12 KB
Binary file not shown.

0 commit comments

Comments
 (0)