Skip to content

Commit 9646244

Browse files
committed
add snowglobe files
1 parent 9d15de0 commit 9646244

File tree

2 files changed

+304
-0
lines changed

2 files changed

+304
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
from random import randrange
2+
import board
3+
import busio
4+
import displayio
5+
from adafruit_st7789 import ST7789
6+
import adafruit_imageload
7+
import adafruit_lis3dh
8+
9+
#---| User Config |---------------
10+
BACKGROUND = "/blinka_dark.bmp" # specify color or background BMP file
11+
12+
NUM_FLAKES = 50 # total number of snowflakes
13+
FLAKE_SHEET = "/flakes_sheet.bmp" # flake sprite sheet
14+
FLAKE_WIDTH = 4 # sprite width
15+
FLAKE_HEIGHT = 4 # sprite height
16+
FLAKE_TRAN_COLOR = 0x000000 # transparency color
17+
18+
SNOW_COLOR = 0xFFFFFF # snow color
19+
20+
SHAKE_THRESHOLD = 27 # shake sensitivity, lower=more sensitive
21+
#---| User Config |---------------
22+
23+
# Accelerometer setup
24+
accelo_i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
25+
accelo = adafruit_lis3dh.LIS3DH_I2C(accelo_i2c, address=0x19)
26+
27+
# Display setup
28+
WIDTH = 240
29+
HEIGHT = 240
30+
displayio.release_displays()
31+
32+
spi = busio.SPI(board.SCL, MOSI=board.SDA)
33+
tft_cs = board.RX
34+
tft_dc = board.TX
35+
tft_backlight = board.A3
36+
37+
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
38+
39+
display = ST7789(display_bus, width=WIDTH, height=HEIGHT, rowstart=80,
40+
backlight_pin=tft_backlight, rotation=180)
41+
42+
# Load background image
43+
try:
44+
bg_bitmap, bg_palette = adafruit_imageload.load(BACKGROUND,
45+
bitmap=displayio.Bitmap,
46+
palette=displayio.Palette)
47+
# Or just use solid color
48+
except:
49+
bg_bitmap = displayio.Bitmap(WIDTH, HEIGHT, 1)
50+
bg_palette = displayio.Palette(1)
51+
bg_palette[0] = BACKGROUND
52+
background = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette)
53+
54+
55+
# Snowflake setup
56+
flake_bitmap, flake_palette = adafruit_imageload.load(FLAKE_SHEET,
57+
bitmap=displayio.Bitmap,
58+
palette=displayio.Palette)
59+
if FLAKE_TRAN_COLOR is not None:
60+
for i, color in enumerate(flake_palette):
61+
if color == FLAKE_TRAN_COLOR:
62+
flake_palette.make_transparent(i)
63+
break
64+
NUM_SPRITES = flake_bitmap.width // FLAKE_WIDTH * flake_bitmap.height // FLAKE_HEIGHT
65+
flake_pos = [0.0] * NUM_FLAKES
66+
flakes = displayio.Group(max_size=NUM_FLAKES)
67+
for _ in range(NUM_FLAKES):
68+
flakes.append(displayio.TileGrid(flake_bitmap, pixel_shader=flake_palette,
69+
width = 1,
70+
height = 1,
71+
tile_width = FLAKE_WIDTH,
72+
tile_height = FLAKE_HEIGHT,
73+
x = randrange(0, WIDTH),
74+
default_tile=randrange(0, NUM_SPRITES)))
75+
76+
# Snowfield setup
77+
snow_depth = [HEIGHT] * WIDTH
78+
snow_palette = displayio.Palette(2)
79+
snow_palette[0] = 0xADAF00 # transparent color
80+
snow_palette[1] = SNOW_COLOR # snow color
81+
snow_palette.make_transparent(0)
82+
snow_bitmap = displayio.Bitmap(WIDTH, HEIGHT, len(snow_palette))
83+
snow = displayio.TileGrid(snow_bitmap, pixel_shader=snow_palette)
84+
85+
# Add everything to display
86+
splash = displayio.Group()
87+
splash.append(background)
88+
splash.append(flakes)
89+
splash.append(snow)
90+
display.show(splash)
91+
92+
def clear_the_snow():
93+
global flakes, flake_pos, snow_depth
94+
display.auto_refresh = False
95+
for flake in flakes:
96+
# set to a random sprite
97+
flake[0] = randrange(0, NUM_SPRITES)
98+
# set to a random x location
99+
flake.x = randrange(0, WIDTH)
100+
# set random y locations, off screen to start
101+
flake_pos = [-1.0*randrange(0, HEIGHT) for _ in range(NUM_FLAKES)]
102+
# reset snow level
103+
snow_depth = [HEIGHT] * WIDTH
104+
# and snow bitmap
105+
for i in range(WIDTH*HEIGHT):
106+
snow_bitmap[i] = 0
107+
display.auto_refresh = True
108+
109+
def add_snow(index, amount, steepness=2):
110+
location = []
111+
# local steepness check
112+
for x in range(index - amount, index + amount):
113+
add = False
114+
if x == 0:
115+
# check depth to right
116+
if snow_depth[x+1] - snow_depth[x] < steepness:
117+
add = True
118+
elif x == WIDTH - 1:
119+
# check depth to left
120+
if snow_depth[x-1] - snow_depth[x] < steepness:
121+
add = True
122+
elif 0 < x < WIDTH - 1:
123+
# check depth to left AND right
124+
if snow_depth[x-1] - snow_depth[x] < steepness and \
125+
snow_depth[x+1] - snow_depth[x] < steepness:
126+
add = True
127+
if add:
128+
location.append(x)
129+
# add where snow is not too steep
130+
for x in location:
131+
new_level = snow_depth[x] - 1
132+
if new_level >= 0:
133+
snow_depth[x] = new_level
134+
snow_bitmap[x, new_level] = 1
135+
136+
while True:
137+
clear_the_snow()
138+
# loop until globe is full of snow
139+
while snow_depth.count(0) < WIDTH:
140+
# check for shake
141+
if accelo.shake(SHAKE_THRESHOLD, 5, 0):
142+
break
143+
# update snowflakes
144+
for i, flake in enumerate(flakes):
145+
# speed based on sprite index
146+
flake_pos[i] += 1 - flake[0] / NUM_SPRITES
147+
# check if snowflake has hit the ground
148+
if flake_pos[i] >= snow_depth[flake.x]:
149+
# add snow where it fell
150+
add_snow(flake.x, FLAKE_WIDTH)
151+
# reset flake to top
152+
flake_pos[i] = 0
153+
# at a new x location
154+
flake.x = randrange(0, WIDTH)
155+
flake.y = int(flake_pos[i])
156+
display.refresh()
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
from random import randrange
2+
import board
3+
import busio
4+
import displayio
5+
from adafruit_st7789 import ST7789
6+
import adafruit_imageload
7+
import adafruit_lis3dh
8+
9+
#---| User Config |---------------
10+
BACKGROUND = 0xAA0000 # specify color or background BMP file
11+
NUM_FLAKES = 50 # total number of snowflakes
12+
SNOW_COLOR = 0xFFFFFF # snow color
13+
SHAKE_THRESHOLD = 27 # shake sensitivity, lower=more sensitive
14+
#---| User Config |---------------
15+
16+
# Accelerometer setup
17+
accelo_i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
18+
accelo = adafruit_lis3dh.LIS3DH_I2C(accelo_i2c, address=0x19)
19+
20+
# Display setup
21+
WIDTH = 240
22+
HEIGHT = 240
23+
displayio.release_displays()
24+
25+
spi = busio.SPI(board.SCL, MOSI=board.SDA)
26+
tft_cs = board.RX
27+
tft_dc = board.TX
28+
tft_backlight = board.A3
29+
30+
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
31+
32+
display = ST7789(display_bus, width=WIDTH, height=HEIGHT, rowstart=80,
33+
backlight_pin=tft_backlight, rotation=180)
34+
35+
# Load background image
36+
try:
37+
bg_bitmap, bg_palette = adafruit_imageload.load(BACKGROUND,
38+
bitmap=displayio.Bitmap,
39+
palette=displayio.Palette)
40+
# Or just use solid color
41+
except:
42+
bg_bitmap = displayio.Bitmap(WIDTH, HEIGHT, 1)
43+
bg_palette = displayio.Palette(1)
44+
bg_palette[0] = BACKGROUND
45+
background = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette)
46+
47+
# Shared palette for snow bitmaps
48+
palette = displayio.Palette(2)
49+
palette[0] = 0xADAF00 # transparent color
50+
palette[1] = SNOW_COLOR # snow color
51+
palette.make_transparent(0)
52+
53+
# Snowflake setup
54+
FLAKES = (
55+
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
56+
0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1,
57+
0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
58+
0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
59+
)
60+
flake_sheet = displayio.Bitmap(12, 4, len(palette))
61+
for i, value in enumerate(FLAKES):
62+
flake_sheet[i] = value
63+
flake_pos = [0.0] * NUM_FLAKES
64+
flakes = displayio.Group(max_size=NUM_FLAKES)
65+
for _ in range(NUM_FLAKES):
66+
flakes.append(displayio.TileGrid(flake_sheet, pixel_shader=palette,
67+
width = 1,
68+
height = 1,
69+
tile_width = 4,
70+
tile_height = 4 ) )
71+
72+
# Snowfield setup
73+
snow_depth = [HEIGHT] * WIDTH
74+
snow_bmp = displayio.Bitmap(WIDTH, HEIGHT, len(palette))
75+
snow = displayio.TileGrid(snow_bmp, pixel_shader=palette)
76+
77+
# Add everything to display
78+
splash = displayio.Group()
79+
splash.append(background)
80+
splash.append(flakes)
81+
splash.append(snow)
82+
display.show(splash)
83+
84+
def clear_the_snow():
85+
global flakes, flake_pos, snow_depth
86+
display.auto_refresh = False
87+
for flake in flakes:
88+
# set to a random sprite
89+
flake[0] = randrange(0, 3)
90+
# set to a random x location
91+
flake.x = randrange(0, WIDTH)
92+
# set random y locations, off screen to start
93+
flake_pos = [-1.0*randrange(0, HEIGHT) for _ in range(NUM_FLAKES)]
94+
# reset snow level
95+
snow_depth = [HEIGHT] * WIDTH
96+
# and snow bitmap
97+
for i in range(WIDTH*HEIGHT):
98+
snow_bmp[i] = 0
99+
display.auto_refresh = True
100+
101+
def add_snow(index, amount, steepness=2):
102+
location = []
103+
# local steepness check
104+
for x in range(index - amount, index + amount):
105+
add = False
106+
if x == 0:
107+
# check depth to right
108+
if snow_depth[x+1] - snow_depth[x] < steepness:
109+
add = True
110+
elif x == WIDTH - 1:
111+
# check depth to left
112+
if snow_depth[x-1] - snow_depth[x] < steepness:
113+
add = True
114+
elif 0 < x < WIDTH - 1:
115+
# check depth to left AND right
116+
if snow_depth[x-1] - snow_depth[x] < steepness and \
117+
snow_depth[x+1] - snow_depth[x] < steepness:
118+
add = True
119+
if add:
120+
location.append(x)
121+
# add where snow is not too steep
122+
for x in location:
123+
new_level = snow_depth[x] - 1
124+
if new_level >= 0:
125+
snow_depth[x] = new_level
126+
snow_bmp[x, new_level] = 1
127+
128+
while True:
129+
clear_the_snow()
130+
# loop until globe is full of snow
131+
while snow_depth.count(0) < WIDTH:
132+
# check for shake
133+
if accelo.shake(SHAKE_THRESHOLD, 5, 0):
134+
break
135+
# update snowflakes
136+
for i, flake in enumerate(flakes):
137+
# speed based on sprite index
138+
flake_pos[i] += 1 - flake[0] / 3
139+
# check if snowflake has hit the ground
140+
if int(flake_pos[i]) >= snow_depth[flake.x]:
141+
# add snow where it fell
142+
add_snow(flake.x, flake[0] + 2)
143+
# reset flake to top
144+
flake_pos[i] = 0
145+
# at a new x location
146+
flake.x = randrange(0, WIDTH)
147+
flake.y = int(flake_pos[i])
148+
display.refresh()

0 commit comments

Comments
 (0)