kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Galactic Unicorn: Backport Cosmic ulab/numpy examples.
rodzic
d750532180
commit
c836f9f8fe
|
@ -0,0 +1,88 @@
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
A random, computer effect.
|
||||||
|
Experiment with the damping, number of spawns and intensity to change the effect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
gu.set_brightness(0.5)
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
|
||||||
|
|
||||||
|
DAMPING_FACTOR = 0.95
|
||||||
|
NUMBER_OF_LIGHTS = 10
|
||||||
|
INTENSITY = 20
|
||||||
|
|
||||||
|
# Fill palette with a yellow
|
||||||
|
r, g, b = (230, 150, 0)
|
||||||
|
PALETTE_ENTRIES = 255
|
||||||
|
for x in range(PALETTE_ENTRIES):
|
||||||
|
_ = graphics.create_pen(r * x // PALETTE_ENTRIES, g * x // PALETTE_ENTRIES, b)
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
computer[:] *= DAMPING_FACTOR
|
||||||
|
|
||||||
|
# Spawn random drops
|
||||||
|
for _ in range(NUMBER_OF_LIGHTS):
|
||||||
|
x = random.randint(0, width - 1)
|
||||||
|
y = random.randint(0, height - 1)
|
||||||
|
computer[y][x] = random.randint(0, INTENSITY)
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the effect to the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(computer, 0, 1) * (PALETTE_ENTRIES - 1), dtype=numpy.uint8).tobytes()
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT
|
||||||
|
computer = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
|
@ -0,0 +1,128 @@
|
||||||
|
import time
|
||||||
|
import gc
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
Classic fire effect.
|
||||||
|
Play with the number of spawns, heat, damping factor and colour palette to tweak it.
|
||||||
|
|
||||||
|
This is vertical because my brain would not let me rotate it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
gu.set_brightness(0.5)
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
|
||||||
|
# Number of random fire spawns
|
||||||
|
FIRE_SPAWNS = 5
|
||||||
|
|
||||||
|
# Fire damping
|
||||||
|
DAMPING_FACTOR = 0.98
|
||||||
|
|
||||||
|
# TURN UP THE HEEEAAT
|
||||||
|
HEAT = 3.0
|
||||||
|
|
||||||
|
# Create the fire palette
|
||||||
|
"""
|
||||||
|
# Raging Gas Inferno
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(20, 20, 20)
|
||||||
|
graphics.create_pen(50, 10, 0)
|
||||||
|
graphics.create_pen(180, 30, 0)
|
||||||
|
graphics.create_pen(220, 160, 0)
|
||||||
|
graphics.create_pen(255, 255, 180)
|
||||||
|
graphics.create_pen(255, 255, 220)
|
||||||
|
graphics.create_pen(90, 90, 255)
|
||||||
|
graphics.create_pen(255, 0, 255)
|
||||||
|
"""
|
||||||
|
# Original Colours
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(20, 20, 20)
|
||||||
|
graphics.create_pen(180, 30, 0)
|
||||||
|
graphics.create_pen(220, 160, 0)
|
||||||
|
graphics.create_pen(255, 255, 180)
|
||||||
|
|
||||||
|
PALETTE_SIZE = 5 # Should match the number of colours defined above
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
# Clear the bottom two rows (off screen)
|
||||||
|
heat[height - 1][:] = 0.0
|
||||||
|
heat[height - 2][:] = 0.0
|
||||||
|
|
||||||
|
# Add random fire spawns
|
||||||
|
for c in range(FIRE_SPAWNS):
|
||||||
|
x = random.randint(0, width - 4) + 2
|
||||||
|
heat[height - 1][x - 1:x + 1] = HEAT / 2.0
|
||||||
|
heat[height - 2][x - 1:x + 1] = HEAT
|
||||||
|
|
||||||
|
# Propagate the fire upwards
|
||||||
|
a = numpy.roll(heat, -1, axis=0) # y + 1, x
|
||||||
|
b = numpy.roll(heat, -2, axis=0) # y + 2, x
|
||||||
|
c = numpy.roll(heat, -1, axis=0) # y + 1
|
||||||
|
d = numpy.roll(c, 1, axis=1) # y + 1, x + 1
|
||||||
|
e = numpy.roll(c, -1, axis=1) # y + 1, x - 1
|
||||||
|
|
||||||
|
# Average over 5 adjacent pixels and apply damping
|
||||||
|
heat[:] += a + b + d + e
|
||||||
|
heat[:] *= DAMPING_FACTOR / 5.0
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the fire effect to the framebuffer
|
||||||
|
# Clips the fire to 0.0 to 1.0
|
||||||
|
# Multiplies it by the number of palette entries (-1) to turn it into a palette index
|
||||||
|
# Converts to uint8_t datatype to match the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(heat[0:11, 0:53], 0, 1) * (PALETTE_SIZE - 1), dtype=numpy.uint8).tobytes()
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT + 4
|
||||||
|
heat = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
|
@ -0,0 +1,120 @@
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
A lava lamp effect, created by blurred, moving particles.
|
||||||
|
|
||||||
|
Oh boy, this one's real lively! Stand your Galactic Unicorn on its side for best effect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
gu.set_brightness(0.5)
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT
|
||||||
|
lava = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
|
||||||
|
class Blob():
|
||||||
|
def __init__(self):
|
||||||
|
self.x = float(random.randint(0, width - 1))
|
||||||
|
self.y = float(random.randint(0, height - 1))
|
||||||
|
self.r = (float(random.randint(0, 40)) / 5.0)
|
||||||
|
self.dx = (float(random.randint(0, 20)) / 80.0)
|
||||||
|
self.dy = (float(random.randint(0, 20)) / 80.0) - 0.15
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
self.x += self.dx
|
||||||
|
self.y += self.dy
|
||||||
|
|
||||||
|
if self.x < 0.0 or self.x >= float(width):
|
||||||
|
self.x = max(0.0, self.x)
|
||||||
|
self.x = min(float(width - 1), self.x)
|
||||||
|
self.dx = -self.dx
|
||||||
|
|
||||||
|
if self.y < 0.0 or self.y >= float(height):
|
||||||
|
self.y = max(0.0, self.y)
|
||||||
|
self.y = min(float(height - 1), self.y)
|
||||||
|
self.dy = -self.dy
|
||||||
|
|
||||||
|
|
||||||
|
blobs = [Blob() for _ in range(10)]
|
||||||
|
|
||||||
|
|
||||||
|
# Fill palette with a steep falloff from bright red to dark blue
|
||||||
|
PAL_COLS = 9
|
||||||
|
for x in range(PAL_COLS):
|
||||||
|
graphics.create_pen_hsv(0.5 + math.log(x + 1, PAL_COLS + 1) / 2.0, 1.0, math.log(x + 1, PAL_COLS + 1))
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
# Update the blobs and draw them into the effect
|
||||||
|
for blob in blobs:
|
||||||
|
blob.move()
|
||||||
|
lava[int(blob.y)][int(blob.x)] = blob.r
|
||||||
|
|
||||||
|
# Propogate the blobs outwards
|
||||||
|
a = numpy.roll(lava, 1, axis=0)
|
||||||
|
b = numpy.roll(lava, -1, axis=0)
|
||||||
|
d = numpy.roll(lava, 1, axis=1)
|
||||||
|
e = numpy.roll(lava, -1, axis=1)
|
||||||
|
|
||||||
|
# Average over 5 adjacent pixels and apply damping
|
||||||
|
lava[:] += a + b + d + e
|
||||||
|
lava[:] *= 0.97 / 5.0
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the lava effect to the framebuffer
|
||||||
|
# Clips to 0.0 - 1.0
|
||||||
|
# Multiplies by palette entries (-1) to turn it into a palette index
|
||||||
|
# Converts to uint8_t datatype to match the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(lava, 0.0, 1.0) * (PAL_COLS - 1), dtype=numpy.uint8).tobytes()
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
|
@ -0,0 +1,88 @@
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
HELLO NEO.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
gu.set_brightness(1.0)
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
|
||||||
|
|
||||||
|
# Fill half the palette with GREEEN
|
||||||
|
for g in range(128):
|
||||||
|
_ = graphics.create_pen(0, g, 0)
|
||||||
|
|
||||||
|
# And half with bright green for white sparkles
|
||||||
|
for g in range(128):
|
||||||
|
_ = graphics.create_pen(128, 128 + g, 128)
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
the_matrix[:] *= 0.65
|
||||||
|
|
||||||
|
x = random.randint(0, width // 2)
|
||||||
|
y = random.randint(0, height - 1)
|
||||||
|
the_matrix[y][x] = random.randint(128, 255) / 255.0
|
||||||
|
|
||||||
|
# Propagate downwards
|
||||||
|
old = numpy.ndarray(the_matrix) * 0.5
|
||||||
|
the_matrix[:] = numpy.roll(the_matrix, 1, axis=1)
|
||||||
|
the_matrix[:] += old
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the effect to the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(the_matrix, 0, 1) * 254, dtype=numpy.uint8).tobytes()
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT
|
||||||
|
the_matrix = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
|
@ -0,0 +1,134 @@
|
||||||
|
import time
|
||||||
|
import gc
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
Classic fire effect.
|
||||||
|
Play with the number of spawns, heat, damping factor and colour palette to tweak it.
|
||||||
|
|
||||||
|
This is vertical because my brain would not let me rotate it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
gu.set_brightness(0.5)
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
|
||||||
|
# Number of random fire spawns
|
||||||
|
FIRE_SPAWNS = 5
|
||||||
|
|
||||||
|
# Fire damping
|
||||||
|
DAMPING_FACTOR = 0.98
|
||||||
|
|
||||||
|
# TURN UP THE HEEEAAT
|
||||||
|
HEAT = 3.0
|
||||||
|
|
||||||
|
# Create the fire palette
|
||||||
|
"""
|
||||||
|
# Raging Gas Inferno
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(20, 20, 20)
|
||||||
|
graphics.create_pen(50, 10, 0)
|
||||||
|
graphics.create_pen(180, 30, 0)
|
||||||
|
graphics.create_pen(220, 160, 0)
|
||||||
|
graphics.create_pen(255, 255, 180)
|
||||||
|
graphics.create_pen(255, 255, 220)
|
||||||
|
graphics.create_pen(90, 90, 255)
|
||||||
|
graphics.create_pen(255, 0, 255)
|
||||||
|
"""
|
||||||
|
# Original Colours
|
||||||
|
graphics.create_pen(0, 0, 0)
|
||||||
|
graphics.create_pen(20, 20, 20)
|
||||||
|
graphics.create_pen(180, 30, 0)
|
||||||
|
graphics.create_pen(220, 160, 0)
|
||||||
|
graphics.create_pen(255, 255, 180)
|
||||||
|
|
||||||
|
PALETTE_SIZE = 5 # Should match the number of colours defined above
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
# Clear the bottom two rows (off screen)
|
||||||
|
heat[height - 1][:] = 0.0
|
||||||
|
heat[height - 2][:] = 0.0
|
||||||
|
|
||||||
|
# Add random fire spawns
|
||||||
|
for c in range(FIRE_SPAWNS):
|
||||||
|
x = random.randint(0, width - 4) + 2
|
||||||
|
heat[height - 1][x - 1:x + 1] = HEAT / 2.0
|
||||||
|
heat[height - 2][x - 1:x + 1] = HEAT
|
||||||
|
|
||||||
|
# Propagate the fire upwards
|
||||||
|
a = numpy.roll(heat, -1, axis=0) # y + 1, x
|
||||||
|
b = numpy.roll(heat, -2, axis=0) # y + 2, x
|
||||||
|
c = numpy.roll(heat, -1, axis=0) # y + 1
|
||||||
|
d = numpy.roll(c, 1, axis=1) # y + 1, x + 1
|
||||||
|
e = numpy.roll(c, -1, axis=1) # y + 1, x - 1
|
||||||
|
|
||||||
|
# Average over 5 adjacent pixels and apply damping
|
||||||
|
heat[:] += a + b + d + e
|
||||||
|
heat[:] *= DAMPING_FACTOR / 5.0
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the fire effect to the framebuffer
|
||||||
|
# Clips the fire to 0.0 to 1.0
|
||||||
|
# Multiplies it by the number of palette entries (-1) to turn it into a palette index
|
||||||
|
# Converts to uint8_t datatype to match the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(heat[0:11, 0:53], 0, 1) * (PALETTE_SIZE - 1), dtype=numpy.uint8).tobytes()
|
||||||
|
|
||||||
|
# Draw text over the top
|
||||||
|
graphics.set_pen(0)
|
||||||
|
graphics.text("This", 1, 2, 1, 1)
|
||||||
|
graphics.text("is", 22, 2, 1, 1)
|
||||||
|
graphics.text("fine", 33, 2, 1, 1)
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT + 4
|
||||||
|
heat = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
|
@ -0,0 +1,97 @@
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from galactic import GalacticUnicorn
|
||||||
|
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN, PEN_P8
|
||||||
|
from ulab import numpy
|
||||||
|
|
||||||
|
"""
|
||||||
|
A random, trippy effect.
|
||||||
|
Experiment with the damping, number of spawns, intensity and offset to change the effect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# MAXIMUM OVERKILL
|
||||||
|
# machine.freq(250_000_000)
|
||||||
|
|
||||||
|
gu = GalacticUnicorn()
|
||||||
|
gu.set_brightness(0.5)
|
||||||
|
graphics = PicoGraphics(DISPLAY_GALACTIC_UNICORN, pen_type=PEN_P8)
|
||||||
|
|
||||||
|
|
||||||
|
DAMPING_FACTOR = 0.95
|
||||||
|
NUMBER_OF_DROPS = 5
|
||||||
|
INTENSITY = 10
|
||||||
|
OFFSET = 0.0 # Try 0.5
|
||||||
|
|
||||||
|
# Fill palette with a rainbow sweep
|
||||||
|
PALETTE_ENTRIES = 255
|
||||||
|
for x in range(PALETTE_ENTRIES):
|
||||||
|
_ = graphics.create_pen_hsv(float(x) / PALETTE_ENTRIES + OFFSET, 1.0, 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
def update():
|
||||||
|
trippy[:] *= DAMPING_FACTOR
|
||||||
|
|
||||||
|
# Spawn random drops
|
||||||
|
for _ in range(NUMBER_OF_DROPS):
|
||||||
|
x = random.randint(0, width - 1)
|
||||||
|
y = random.randint(0, height - 1)
|
||||||
|
trippy[y][x] = random.randint(0, INTENSITY)
|
||||||
|
|
||||||
|
a = numpy.roll(trippy, 1, axis=0)
|
||||||
|
b = numpy.roll(trippy, -1, axis=0)
|
||||||
|
d = numpy.roll(trippy, 1, axis=1)
|
||||||
|
e = numpy.roll(trippy, -1, axis=1)
|
||||||
|
|
||||||
|
# Average over 5 adjacent pixels and apply damping
|
||||||
|
trippy[:] += a + b + d + e
|
||||||
|
trippy[:] /= 5.0
|
||||||
|
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
# Copy the effect to the framebuffer
|
||||||
|
memoryview(graphics)[:] = numpy.ndarray(numpy.clip(trippy, 0, 1) * (PALETTE_ENTRIES - 1), dtype=numpy.uint8).tobytes()
|
||||||
|
gu.update(graphics)
|
||||||
|
|
||||||
|
|
||||||
|
width = GalacticUnicorn.WIDTH
|
||||||
|
height = GalacticUnicorn.HEIGHT
|
||||||
|
trippy = numpy.zeros((height, width))
|
||||||
|
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||||
|
gu.adjust_brightness(+0.01)
|
||||||
|
|
||||||
|
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||||
|
gu.adjust_brightness(-0.01)
|
||||||
|
|
||||||
|
tstart = time.ticks_ms()
|
||||||
|
gc.collect()
|
||||||
|
update()
|
||||||
|
draw()
|
||||||
|
tfinish = time.ticks_ms()
|
||||||
|
|
||||||
|
total = tfinish - tstart
|
||||||
|
t_total += total
|
||||||
|
t_count += 1
|
||||||
|
|
||||||
|
if t_count == 60:
|
||||||
|
per_frame_avg = t_total / t_count
|
||||||
|
print(f"60 frames in {t_total}ms, avg {per_frame_avg:.02f}ms per frame, {1000/per_frame_avg:.02f} FPS")
|
||||||
|
t_count = 0
|
||||||
|
t_total = 0
|
||||||
|
|
||||||
|
# pause for a moment (important or the USB serial device will fail)
|
||||||
|
# try to pace at 60fps or 30fps
|
||||||
|
if total > 1000 / 30:
|
||||||
|
time.sleep(0.0001)
|
||||||
|
elif total > 1000 / 60:
|
||||||
|
t = 1000 / 30 - total
|
||||||
|
time.sleep(t / 1000)
|
||||||
|
else:
|
||||||
|
t = 1000 / 60 - total
|
||||||
|
time.sleep(t / 1000)
|
Ładowanie…
Reference in New Issue