I was thinking: "What kind of game can I do on a 6x12 screen?" What I came up with was a gauntlet game. This is sort of like a running game and much like early racing games (early as in Atari 2600) in that the track continually advances and swerves, and the player has to stay on it. I added the extra feature of having randomly spawning targets that add to the players score when they are hit. Finally if the player hits the edge of the track the score and number of steps is output to the console and the game restarts.
I’ll be showing edited snippets of the code as I discuss various aspects. The full code is at the end of this page and in the examples directory of the library.
import time import random import board import busio import dotstar_featherwing import Adafruit_seesaw i2c = busio.I2C(board.SCL, board.SDA) ss = Adafruit_seesaw.Seesaw(i2c) wing = dotstar_featherwing.DotstarFeatherwing(board.D13, board.D11, 0.1) black = 0x000000 wall = 0x200800 # must not have any blue, must have red pellet = 0x000040 # must have blue player = 0x00FF00
The reason the wall and pellet colors have the noted constraints is to simplify (and thus optimize for space) the tests later.
Making the track
The first thing that was needed was a way to shift a row onto the display from the top. I added a method to do that to the library. I added a slight change from the left/right shifting methods: an offset into the slice at which to start taking 12 pixels. By randomly changing the offset into a slice that is wider than the 12 column display I can make the track swerve back and forth.
row = (wall, wall, wall, wall, wall, wall, wall, wall, black, black, black, black, black, wall, wall, wall, wall, wall, wall, wall, wall) offset = 4 # ... offset = min(max(0, offset + random.randint(-1, 1)), 9) wing.shift_into_top(row, offset)
The main loop simply adjusts the offset like that and shifts into the top (edited to show just the track creation):
while True: offset = min(max(0, offset + random.randint(-1, 1)), 9) wing.shift_into_top(row, offset) wing.show() time.sleep(0.1)
The player
Next we need a player sprite. We need to be able to move the player sprite back & forth to stay on the track. That's where the Joy FeatherWing comes in. Functionally it's a Seesaw and we use the Seesaw library to interact with it. In this case interaction is simple reading the horizontal axis of the thumbstick.
wing.set_color(3, player_x, black) joy_x = ss.analog_read(3) if joy_x < 256 and player_x > 0: player_x -= 1 elif joy_x > 768 and player_x < 11: player_x += 1 wing.set_color(3, player_x, player)
Score pellets
To add a goal I spawn a score pellet with a 5% chance each time through the loop. If the player maneuvers their sprite over a score pellet they get a point.
The score pellet only needs to be initially placed; the shifting/scrolling will take care of moving it.
if random.randint(1, 20) == 1: wing.set_color(0, random.randint(8, 12) - offset, pellet)
Collisions
There are two things that the player sprite can collide with: the wall and a score pellet.
Colliding with the wall causes the game to end, print the players score and number of steps they survived to the console, and start a fresh game.
Colliding with a pellet increments the score.
This is where the pellet having blue in it, and the wall having red and no blue comes into play to drastically simplify the check.
r, _, b = wing.get_color(3, player_x) if b: score += 1 elif r: return score
I also have it increment the score every 25 iterations and increase the speed every 100.
steps += 1 if steps % 25 == 0: score += 1 if steps % 100 == 0: step_delay *= 0.9 sleep(step_delay)
Notice that in the case of a wall collision, the function returns the number of steps and score. The top level code in main.py calls the game function that I've been describing, prints the returned values, flashes the screen red, and loops.
while True: result = run() # got here because of a crash, so report score and restart wing.shift_in_string(numbers, '{:03d}'.format(result), 0x101010) sleep(5)
# The MIT License (MIT) # # Copyright (c) 2018 Dave Astels # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ A gaunlet running game using the dotstar wing and the joy wing. """ from time import sleep from random import randint import board import busio import dotstar_featherwing import Adafruit_seesaw i2c = busio.I2C(board.SCL, board.SDA) ss = Adafruit_seesaw.Seesaw(i2c) wing = dotstar_featherwing.DotstarFeatherwing(board.D13, board.D11, 0.1) black = 0x000000 wall = 0x200800 # must not have any blue, must have red pellet = 0x000040 # must have blue player = 0x00FF00 numbers = { ' ': [0, 0, 0], '0': [30, 33, 30], '1': [34, 63, 32], '2': [50, 41, 38], '3': [33, 37, 26], '4': [ 7, 4, 63], '5': [23, 37, 25], '6': [30, 41, 25], '7': [49, 9, 7], '8': [26, 37, 26], '9': [38, 41, 30], } row = (wall, wall, wall, wall, wall, wall, wall, wall, black, black, black, black, black, wall, wall, wall, wall, wall, wall, wall, wall) def run(): """Play the game.""" player_x = 6 score = 0 steps = 0 step_delay = 0.15 offset = 4 for _ in range(wing.rows): wing.shift_into_top(row, offset) wing.show() while True: # remove player sprite wing.set_color(3, player_x, black) # shift/advance the track offset = min(max(0, offset + randint(-1, 1)), 9) wing.shift_into_top(row, offset) # Maybe add a pellet if randint(1, 20) == 1: wing.set_color(0, randint(8, 12) - offset, pellet) # Adjust player position joy_x = ss.analog_read(3) if joy_x < 256 and player_x > 0: player_x -= 1 elif joy_x > 768 and player_x < 11: player_x += 1 # Check for collisions r, _, b = wing.get_color(3, player_x) if b: score += 1 elif r: return score # Show player sprite wing.set_color(3, player_x, player) # Update some things and sleep a bit wing.show() steps += 1 if steps % 25 == 0: score += 1 if steps % 100 == 0: step_delay *= 0.9 sleep(step_delay) while True: result = run() # got here because of a crash, so report score and restart wing.shift_in_string(numbers, '{:03d}'.format(result), 0x101010) sleep(5)
Text editor powered by tinymce.