CIRCUITPYcode.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, open the directory PyBadge_Blinka_Jump_Game/ and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your CIRCUITPY drive.
CIRCUITPY
# SPDX-FileCopyrightText: 2020 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
from random import randint
from micropython import const
import board
import terminalio
import displayio
import adafruit_imageload
import digitalio
import simpleio
from keypad import ShiftRegisterKeys, Event
from adafruit_display_text import label
# setup for PyBadge buttons
BUTTON_LEFT = const(7)
BUTTON_UP = const(6)
BUTTON_DOWN = const(5)
BUTTON_RIGHT = const(4)
BUTTON_SEL = const(3)
BUTTON_START = const(2)
BUTTON_A = const(1)
BUTTON_B = const(0)
pad = ShiftRegisterKeys(clock=board.BUTTON_CLOCK,
data=board.BUTTON_OUT,
latch=board.BUTTON_LATCH,
key_count=8,
value_when_pressed=True,
max_events=1)
latest_event = Event(key_number=8)
last_read = 0
# enables speaker
speakerEnable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speakerEnable.switch_to_output(value=True)
# Sprite cell values
EMPTY = 0
BLINKA_1 = 1
BLINKA_2 = 2
SPARKY = 3
HEART = 4
JUMP_1 = 5
JUMP_2 = 6
# creates display
display = board.DISPLAY
# scale=2 allows the sprites to be bigger
group = displayio.Group(scale=2)
# Blinka sprite setup
blinka, blinka_pal = adafruit_imageload.load("/spritesNew.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
# creates a transparent background for Blinka
blinka_pal.make_transparent(7)
blinka_grid = displayio.TileGrid(blinka, pixel_shader=blinka_pal,
width=2, height=1,
tile_height=16, tile_width=16,
default_tile=EMPTY)
blinka_grid.x = 0
blinka_grid.y = 32
blinka_group = displayio.Group()
blinka_group.append(blinka_grid)
# first Sparky sprite
sparky0, sparky0_pal = adafruit_imageload.load("/spritesNew.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
sparky0_pal.make_transparent(7)
sparky0_grid = displayio.TileGrid(sparky0, pixel_shader=sparky0_pal,
width=1, height=1,
tile_height=16, tile_width=16,
default_tile=SPARKY)
# all Sparky sprites begin off screen
sparky0_grid.x = 100
sparky0_grid.y = 32
sparky0_group = displayio.Group()
sparky0_group.append(sparky0_grid)
# 2nd Sparky sprite
sparky1, sparky1_pal = adafruit_imageload.load("/spritesNew.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
sparky1_pal.make_transparent(7)
sparky1_grid = displayio.TileGrid(sparky1, pixel_shader=sparky1_pal,
width=1, height=1,
tile_height=16, tile_width=16,
default_tile=SPARKY)
sparky1_grid.x = 100
sparky1_grid.y = 32
sparky1_group = displayio.Group()
sparky1_group.append(sparky1_grid)
# 3rd Sparky sprite
sparky2, sparky2_pal = adafruit_imageload.load("/spritesNew.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
sparky2_pal.make_transparent(7)
sparky2_grid = displayio.TileGrid(sparky2, pixel_shader=sparky2_pal,
width=1, height=1,
tile_height=16, tile_width=16,
default_tile=SPARKY)
sparky2_grid.x = 100
sparky2_grid.y = 32
sparky2_group = displayio.Group()
sparky2_group.append(sparky2_grid)
# heart sprite group
life_bit, life_pal = adafruit_imageload.load("/spritesNew.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
life_grid = displayio.TileGrid(life_bit, pixel_shader=life_pal,
width=3, height=1,
tile_height=16, tile_width=16,
default_tile=HEART)
life_group = displayio.Group()
life_group.append(life_grid)
# adding all graphics groups to the main display group
group.append(blinka_group)
group.append(sparky0_group)
group.append(sparky1_group)
group.append(sparky2_group)
group.append(life_group)
# text area for the running score
score_text = " "
font = terminalio.FONT
score_color = 0x0000FF
# text for "game over" graphic
game_over_text = label.Label(font, text = " ", color = 0xFF00FF)
# score text
score_area = label.Label(font, text=score_text, color=score_color)
# text for "new game" graphic
new_game_text = label.Label(font, text = " ", color = 0xFF00FF)
# coordinants for text areas
score_area.x = 57
score_area.y = 6
game_over_text.x = 13
game_over_text.y = 30
new_game_text.x = 8
new_game_text.y = 30
# creating a text display group
text_group = displayio.Group()
text_group.append(score_area)
text_group.append(game_over_text)
text_group.append(new_game_text)
# adding text group to main display group
group.append(text_group)
# displaying main display group
display.root_group = group
# state for hit detection
crash = False
# states to see if a Sparky is on screen
sparky0 = False
sparky1 = False
sparky2 = False
# array of Sparky states
sparky_states = [sparky0, sparky1, sparky2]
# array of x location for Sparky's
sparky_x = [sparky0_grid.x, sparky1_grid.x, sparky2_grid.x]
# function to display the heart sprites for lives
def life():
for _ in range(0, 3):
life_grid[_, 0] = EMPTY
for hearts in range(life_count):
life_grid[hearts, 0] = HEART
# lives at beginning of the game
life_count = 3
# variables for scoring
jump_score = 0
total_score = 0
bonus = 0
# state for Blinka being in default 'slither' mode
snake = True
# state to check if Blinka has jumped over Sparky
cleared = False
# state for the end of a game
end = False
# state for a new game beginning
new_game = True
# state for detecting game over
game_over = False
# variable to change between Blinka's two slither sprites
b = 1
# variable to hold time.monotonic() count for Blinka slither animation
slither = 0
# variables to hold time.monotonic() count to delay Sparky spawning
blue = 0
smoke = 0
monster = 0
# jump button press state
jump_pressed = False
while True:
# checks if button has been pressed
if (last_read + 0.01) < time.monotonic():
pad.events.get_into(latest_event)
last_read = time.monotonic()
# new game
if new_game and not game_over:
# graphics for new game splash screen
blinka_grid.y = 16
blinka_grid[0] = JUMP_1
blinka_grid[1] = JUMP_2
sparky0_grid.x = 5
sparky1_grid.x = 40
sparky2_grid.x = 65
score_area.text = str(300)
new_game_text.text = "BLINKA JUMP"
life()
# if start is pressed...
if latest_event:
if latest_event.key_number == BUTTON_START:
# prepares display for gameplay
print("start game")
new_game_text.text = " "
life_count = 3
start = time.monotonic()
new_game = False
end = False
sparky0_grid.x = 100
sparky1_grid.x = 100
sparky2_grid.x = 100
# if game has started...
if not game_over and not new_game:
# gets time.monotonic() to have a running score
mono = time.monotonic()
score = mono - start
# adds 10 points every time a Sparky is cleared
total_score = score + jump_score
# displays score as text
score_area.text = str(int(total_score))
# puts Sparky states and x location into callable arrays
for s in range(3):
sparky_state = sparky_states[s]
sparky_location = sparky_x[s]
# Sparkys are generated using a staggered delay
# and matching an int to a random int
# 1st Sparky
if (blue + 0.03) < time.monotonic():
if randint(1, 15) == 3:
sparky_states[0] = True
blue = time.monotonic()
# 2nd Sparky
if (smoke + 0.07) < time.monotonic():
if randint(1, 15) == 7:
sparky_states[1] = True
smoke = time.monotonic()
# 3rd Sparky
if (monster + 0.12) < time.monotonic():
if randint(1, 15) == 12:
sparky_states[2] = True
monster = time.monotonic()
# if a Sparky is generated, it scrolls across the screen 1 pixel at a time
# 1st Sparky
if sparky_states[0] is True:
sparky0_grid.x -= 1
sparky_x[0] = sparky0_grid.x
display.refresh(target_frames_per_second=120)
# when a Sparky is 16 pixels off the display,
# it goes back to its starting position
if sparky0_grid.x is -16:
sparky_states[0] = False
sparky0_grid.x = 100
sparky_x[0] = sparky0_grid.x
# 2nd Sparky
if sparky_states[1] is True:
sparky1_grid.x -= 1
sparky_x[1] = sparky1_grid.x
display.refresh(target_frames_per_second=120)
if sparky1_grid.x is -16:
sparky_states[1] = False
sparky1_grid.x = 100
sparky_x[1] = sparky1_grid.x
# 3rd Sparky
if sparky_states[2] is True:
sparky2_grid.x -= 1
sparky_x[2] = sparky2_grid.x
display.refresh(target_frames_per_second=120)
if sparky2_grid.x is -16:
sparky_states[2] = False
sparky2_grid.x = 100
sparky_x[2] = sparky2_grid.x
# if no lives are left then the game ends
if life_count is 0:
game_over = True
# if the A button is pressed then Blinka is no longer in the default
# slither animation aka she jumps
if latest_event.key_number == BUTTON_A:
if latest_event.pressed:
jump_pressed = True
snake = False
else:
jump_pressed = False
snake = True
# heart sprites are displayed to show life count
life()
# if Blinka is slithering...
if snake:
# Blinka default location
blinka_grid.y = 32
# empty 2nd tile so that the jump sprite can be shown using
# the same tilegrid
blinka_grid[1] = EMPTY
# every .15 seconds Blinka's slither sprite changes
# so that her slithering is animated
# b holds tilegrid position to display correct sprite
if (slither + 0.15) < time.monotonic():
blinka_grid[0] = b
b += 1
slither = time.monotonic()
if b > 2:
b = 1
# if a Sparky collides with Blinka while she is slithering...
for s in range(3):
if sparky_x[s] == 8 and blinka_grid.y == 32:
# tone is played
simpleio.tone(board.SPEAKER, 493.88, 0.05)
simpleio.tone(board.SPEAKER, 349.23, 0.05)
# lose a life
life_count = life_count - 1
# if the A button is pressed then...
else:
# Blinka JUMPS
# y location changes one row up and both jump sprites are shown
blinka_grid.y = 16
blinka_grid[0] = JUMP_1
blinka_grid[1] = JUMP_2
# if Blinka jumps over a Sparky...
for j in range(3):
if sparky_x[j] == 8 and not cleared:
# 10 points to the player
bonus += 1
jump_score = bonus * 10
cleared = True
# special victory tone is played
simpleio.tone(board.SPEAKER, 523.25, 0.005)
simpleio.tone(board.SPEAKER, 783.99, 0.005)
if not jump_pressed:
# resets back to Blinka animation
snake = True
# resets that Blinka has not jumped over a Sparky
cleared = False
# if there are no more lives, the game is over
if game_over and not new_game:
# game over text is displayed
game_over_text.text = "GAME OVER"
score_area.text = " "
# end game tone is played
# and then the screen holds with the last
# sprites on screen and game over text
if not end:
simpleio.tone(board.SPEAKER, 220, 0.05)
simpleio.tone(board.SPEAKER, 207.65, 0.05)
simpleio.tone(board.SPEAKER, 196, 0.5)
end = True
# if the start button is pressed...
if latest_event and game_over:
if latest_event.key_number == BUTTON_START:
# display, states and score are reset for gameplay
game_over_text.text = " "
life_count = 3
start = time.monotonic()
game_over = False
end = False
total_score = 0
jump_score = 0
bonus = 0
score = 0
blue = 0
smoke = 0
monster = 0
sparky0_grid.x = 100
sparky1_grid.x = 100
sparky2_grid.x = 100
# game begins again with all Sparky's off screen
Page last edited January 22, 2025
Text editor powered by tinymce.