Import the Libraries

The code begins by importing the libraries.

import time
import displayio
from adafruit_circuitplayground import cp
import adafruit_imageload
from adafruit_gizmo import tft_gizmo
from adafruit_display_shapes.circle import Circle

Setup the Display

The TFT Gizmo's display is setup.

#  setup for the Gizmo TFT
display = tft_gizmo.TFT_Gizmo()

Graphics: Background and Crescent Moon

The background image and the crescent moon are imported using the adafruit_imageload library.

The crescent moon is a sprite sheet. This allows it to be split into a TileGrid and iterated through so that it appears to be animated.

The background of the crescent moon is black and is made transparent using the make_transparent() function. This lets the crescent moon shape appear by itself in front of the background image.

#  loading the background image
bg_bitmap, bg_palette = adafruit_imageload.load("/clouds_bg.bmp",
                                         bitmap=displayio.Bitmap,
                                         palette=displayio.Palette)
bg_grid = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette)

#  loading the crescent moon bitmap sequence
bitmap, palette = adafruit_imageload.load("/moon_anime.bmp",
                                         bitmap=displayio.Bitmap,
                                         palette=displayio.Palette)
#  makes the black background transparent so we only see the cresent moon
palette.make_transparent(0)

tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette, width = 1, height = 1,
                               tile_height = 120, tile_width = 120,
                               default_tile = 0)

Graphics: Center Jewel

The "jewel" in the center of the locket is made using the adafruit_display_shapes library to create two Circles that are layered.

#  two circles for the center "jewel"
jewel_outline = Circle(x0=120, y0=120, r=40, fill=0xfbf236)
jewel = Circle(x0=120, y0=120, r=35, fill=0xf70570)

Graphics: Groups

With three different graphical elements, a few groups are created to keep them organized. jewel_splash holds the two circles representing the jewel in the center of the display.

#  adding the two jewel circle elements to a group
jewel_splash = displayio.Group(max_size=20)
jewel_splash.append(jewel_outline)
jewel_splash.append(jewel)

moon_group holds the crescent moon sprite sheet and main_group acts as the group with all of the graphical elements.

#  making a group for the crescent moon sequence
#  scale is 2 because at full 240x240 resolution image is too big
moon_group = displayio.Group(scale = 2)
#  group to hold all of the display elements
main_group = displayio.Group()

The order in which the graphics are added to the main_group matters. First, the background image is added, followed by the crescent moon and finally the jewel.

#  adding the crescent moon tile grid to the moon group
moon_group.append(tile_grid)
#  adding the background to the main group
main_group.append(bg_grid)
#  adding the moon group to the main group
main_group.append(moon_group)
#  adding the jewel circles to the main group
main_group.append(jewel_splash)

#  showing the main group on the display
display.show(main_group)

State Machines

A few state machines are setup. Their functions are commented in the code.

#  tracks the tilegrid index location for the crescent moon
moon = 0
#  holds time.monotonic()
crescent = 0
#  a button debouncing
a_pressed = False
#  b button debouncing
b_pressed = False
#  tracks if music is playing
music_playing = False
#  tracks if animation is paused
animation_pause = False

The Loop

The loop begins by debouncing the Circuit Playground Bluefruit's buttons.

while True:
    #  button debouncing
    if not cp.button_a and a_pressed:
        a_pressed = False
    if not cp.button_b and b_pressed:
        b_pressed = False

Animating the Crescent Moon

An if statement runs the crescent moon animation. Every .8 seconds, the tile_grid advances its index position, showing the next frame of the crescent moon's sprite sheet.

#  runs crescent moon animation
    if not music_playing and not animation_pause:
        #  every .8 seconds...
        if (crescent + .8) < time.monotonic():
            #  the moon animation cycles
            tile_grid[0] = moon
            #  moon is the tilegrid index location
            moon += 1
            #  resets timer
            crescent = time.monotonic()
            #  resets tilegrid index
            if moon > 35:
                moon = 0

Play the Music

The you press the A button on the Circuit Playground Bluefruit, the song will begin playing through the speaker. 

if not music_playing and (cp.button_a and not a_pressed):
        #  music begins playing and will loop
        music_playing = True
        a_pressed = True
        print("music playing")
        #  song plays once
        cp.play_file("moonlight_densetsu.wav")
        #  music_playing state is updated
        music_playing = False

Pause the Animation

If you want to pause the animation to admire the crescent moon, press the B button. The crescent moon will stop rotating.

#  if the animation IS playing and you press the b button...
    if not animation_pause and (cp.button_b and not b_pressed):
        #  the animation pauses by updating the animation_pause state
        animation_pause = True
        b_pressed = True
        #  debugging REPL message
        print("animation paused")

Restart the Animation

To resume the animation, you can press the B button again and the crescent moon will continue its orbit right where it left off.

#  if the animation is PAUSED and you press the b button...
    if animation_pause and (cp.button_b and not b_pressed):
        #  the animation begins again by updating the animation_pause state
        animation_pause = False
        b_pressed = True
        #  debugging REPL message
        print("animation running again")

This guide was first published on Apr 06, 2021. It was last updated on 2021-04-06 16:43:45 -0400.

This page (CircuitPython Code Walkthrough) was last updated on Oct 12, 2021.

Text editor powered by tinymce.