Skip to content

Commit c0335d5

Browse files
committed
flame sim example
demo example that simulates small flame in display - with masking for shape
1 parent 1e1ea9d commit c0335d5

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

examples/flame_simulation.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
### Flame simulation on the Microbit.
2+
### Author: M. Schafer 2016
3+
# This program has been placed into the public domain.
4+
5+
import microbit, random
6+
7+
# User adjustable values for range of brightness in flames.
8+
MIN_BRIGHTNESS = 1
9+
MAX_BRIGHTNESS = 8
10+
11+
12+
# fixed for the Microbit
13+
DISPLAY_WIDTH = 5
14+
DISPLAY_HEIGHT = 5
15+
16+
INVERT_DISPLAY = True # flame can be oriented in either direction
17+
18+
# MASK to create fire shape. multiplies values %
19+
MASK = [[ 88, 100, 100, 100, 88 ],
20+
[ 60, 95, 100, 95, 60 ],
21+
[ 50, 88, 90, 88, 50 ],
22+
[ 33, 75, 88, 75, 33 ],
23+
[ 10, 33, 66, 33, 10 ] ]
24+
25+
# Generate a new bottom row of random values for the flames
26+
def generate_line(start=MIN_BRIGHTNESS, end=MAX_BRIGHTNESS):
27+
"start and end define range of dimmest to brightest 'flames'"
28+
return [start + random.randrange(end-start) for i in range(DISPLAY_WIDTH)]
29+
30+
# shift all values in the grid up one row
31+
def shift_up(grid, newline):
32+
"Shift up lines in grid, add newline at bottom"
33+
for y in range(DISPLAY_HEIGHT-1, 0, -1):
34+
grid[y] = grid[y-1]
35+
# lowest line
36+
for x in range(DISPLAY_WIDTH):
37+
grid[0] = newline
38+
39+
40+
# write a frame to the screen.
41+
# Interpolate values based on percent
42+
def interpolate_frame(screen, pcnt, grid, line):
43+
""" Interpolate new values by reading from grid and
44+
writing to the screen """
45+
# each row interpolates with the one before it
46+
for y in range(DISPLAY_HEIGHT-1, 0, -1):
47+
for x in range(DISPLAY_WIDTH):
48+
mask = MASK[y][x]
49+
newval = ((100-pcnt) * grid[y][x] + pcnt * grid[y-1][x] ) / 100.0
50+
newval = mask * newval / 100.0
51+
if INVERT_DISPLAY:
52+
screen.set_pixel(x, DISPLAY_HEIGHT-y-1, int(newval))
53+
else:
54+
screen.set_pixel(x, y, int(newval))
55+
# first row interpolates with the "next" line
56+
for x in range(DISPLAY_WIDTH):
57+
mask = MASK[y][x]
58+
newval = ((100-pcnt) * grid[0][x] + pcnt * line[x]) / 100.0
59+
newval = mask * newval / 100.0
60+
if INVERT_DISPLAY:
61+
screen.set_pixel(x, DISPLAY_HEIGHT-1, int(newval))
62+
else:
63+
screen.set_pixel(x, 0, int(newval))
64+
65+
## Setup
66+
line = generate_line()
67+
grid = [[0 for i in range(DISPLAY_WIDTH)] for i in range(DISPLAY_HEIGHT)]
68+
69+
SCREEN = microbit.display
70+
percent = 0 # counter to see when to re-interpolate
71+
sleeptime = 0 # delay between updates
72+
percent_increment = 25 # how fast we interpolate fire
73+
74+
75+
# loop forever
76+
while True:
77+
if percent > 100:
78+
# move everything up a line, insert new bottom row
79+
line = generate_line()
80+
shift_up(grid, line)
81+
percent = 0
82+
83+
# Check Buttons to see if changing
84+
# button_a = smoothness
85+
if microbit.button_a.was_pressed():
86+
percent_increment += 5
87+
if percent_increment > 50:
88+
percent_increment = 1
89+
print("percent interpolate=", percent_increment)
90+
# button_b = delay
91+
if microbit.button_b.was_pressed():
92+
sleeptime += 10
93+
if sleeptime > 100:
94+
sleeptime = 0
95+
print("sleeptime=", sleeptime)
96+
# draw frame and sleep
97+
interpolate_frame(SCREEN, percent, grid, line)
98+
microbit.sleep(sleeptime)
99+
# update main counters
100+
percent += percent_increment
101+

0 commit comments

Comments
 (0)