85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
# Standalone MicroPython Voice Animation: Success Spark
|
|
# Exposes run(text="", frames=...) and runs automatically if executed directly.
|
|
import time
|
|
import math
|
|
|
|
try:
|
|
import board_config
|
|
display = getattr(board_config, 'display_instance', None)
|
|
except Exception:
|
|
board_config = None
|
|
display = None
|
|
|
|
def draw_center_text(d, msg, y, w, scale=1, c=1):
|
|
char_w = 8 * scale
|
|
x = max(0, (w - len(msg) * char_w) // 2)
|
|
if hasattr(d, 'text_large') and scale > 1:
|
|
try:
|
|
d.text_large(msg, x, y, scale, c)
|
|
return
|
|
except Exception:
|
|
pass
|
|
d.text(msg, x, y, c)
|
|
|
|
def run(text="", frames=100):
|
|
if not display:
|
|
print("board_config.display_instance is not available. Skipping animation.")
|
|
return
|
|
|
|
width = getattr(display, 'width', 400)
|
|
height = getattr(display, 'height', 300)
|
|
cx, cy = width // 2, height // 2
|
|
|
|
label = text if text else "SUCCESS!"
|
|
frame = 0
|
|
|
|
try:
|
|
while True:
|
|
if frames is not None and frames > 0 and frame >= frames:
|
|
break
|
|
|
|
display.clear(0)
|
|
|
|
# Draw a thick success checkmark
|
|
display.line(cx - 20, cy + 5, cx - 5, cy + 20, 1)
|
|
display.line(cx - 19, cy + 5, cx - 4, cy + 20, 1)
|
|
display.line(cx - 5, cy + 20, cx + 25, cy - 10, 1)
|
|
display.line(cx - 4, cy + 20, cx + 26, cy - 10, 1)
|
|
|
|
# Sparkles/rays radiating outwards
|
|
# The rays expand from r=30 to r=90 and loop
|
|
dist = (frame * 6) % 80
|
|
|
|
# Draw rays only if within reasonable expansion bounds
|
|
if dist < 65:
|
|
for angle_deg in range(0, 360, 45):
|
|
angle = math.radians(angle_deg)
|
|
# Outer point of sparkle
|
|
sx1 = cx + int(dist * math.cos(angle))
|
|
sy1 = cy + int(dist * math.sin(angle))
|
|
# Inner point of sparkle
|
|
sx2 = cx + int((dist + 12) * math.cos(angle))
|
|
sy2 = cy + int((dist + 12) * math.sin(angle))
|
|
|
|
display.line(sx1, sy1, sx2, sy2, 1)
|
|
|
|
# Add side sparkles for variety on cross angles (45, 135, etc.)
|
|
if angle_deg % 90 != 0:
|
|
display.fill_rect(sx2 - 2, sy2 - 2, 4, 4, 1)
|
|
|
|
# Draw centered text label at the bottom
|
|
draw_center_text(display, label, height - 30, width, scale=1, c=1)
|
|
|
|
display.show()
|
|
frame += 1
|
|
|
|
try:
|
|
time.sleep_ms(45)
|
|
except AttributeError:
|
|
time.sleep(0.045)
|
|
except KeyboardInterrupt:
|
|
print("Animation interrupted by user.")
|
|
|
|
if __name__ in ('__main__', '__name__'):
|
|
run()
|