Coding the Lights

What I thought would be a good way to implement the light support for this game is to have a function that I can call to light up the selected regions for a given amount of time. By calling this function repeatedly I would then achieve the effect of playing a light sequence.

Let's call this function light_region(). The first argument is going to be the region, which will be given as 0, 1, 2 or 3 for the four light regions in the game. The second argument is going to be the duration for the light to stay on, and for convenience I will make this argument have a default of one second. Here is how the function will look:

Download: file
def light_region(region, duration=1):
    # TODO!

To implement the logic in this function, we have the problem of knowing which LEDs need to be turned on for the given region argument. A very convenient way to do this is to use a tuple of four tuple elements that map to the four regions. Each element of this tuple then contains the LEDs that belong to that region as a tuple.

Download: file
REGION_LEDS = (
    (5, 6, 7),  # yellow region
    (2, 3, 4),  # blue region
    (7, 8, 9),  # red region
    (0, 1, 2),  # green region
)

This is great, because now I can use the expression REGION_LEDS[region] to know which LED indexes I need to turn on. The same concept can be applied to the region colors, using another tuple:

Download: file
REGION_COLOR = (
    (255, 255, 0),  # yellow region
    (0, 0, 255),    # blue region
    (255, 0, 0),    # red region
    (0, 255, 0),    # green region
)

Having these two lists makes implementing the light_region() function much easier. Recall that this is the core idea of bottom-up development. We start from the trivial, and slowly move our way up to the more complex and challenging tasks using what's already built as support.

Now I'm ready to show you the first humble version of the Simon game. Before you copy the code I'll show you below, make sure that your Circuit Playground Express board is connected to your computer and your Mu editor is running with the Serial panel visible. If the main window of your editor shows some older code, click the New button to start a brand new file on which to write this game.

When you are ready, write (or copy and paste) the following code in your text editor window:

Download: file
import time
from adafruit_circuitplayground.express import cpx

cpx.pixels.brightness = 0.1  # adjust brightness to your liking

REGION_LEDS = (
    (5, 6, 7),  # yellow region
    (2, 3, 4),  # blue region
    (7, 8, 9),  # red region
    (0, 1, 2),  # green region
)

REGION_COLOR = (
    (255, 255, 0),  # yellow region
    (0, 0, 255),    # blue region
    (255, 0, 0),    # red region
    (0, 255, 0),    # green region
)

def light_region(region, duration=1):
    # turn the LEDs for the selected region on
    for led in REGION_LEDS[region]:
        cpx.pixels[led] = REGION_COLOR[region]
    
    # wait the requested amount of time
    time.sleep(duration)
    
    # turn the LEDs for the selected region off
    for led in REGION_LEDS[region]:
        cpx.pixels[led] = (0, 0, 0)

By now you should understand most of this code. There are two imports, the time and cpx libraries. You are already familiar with cpx, but I haven't mentioned time before, which I'm going to use to implement the duration argument of the light_region() function. I have included the global brightness setting for the NeoPixels, which you can set to the level that works best for you.

The implementation of the light_region() function is fairly simple, because it builds on the support provided by the REGION_LEDS and REGION_COLOR lists, which I included above the function. The first part of the function turns on the three LEDs associated with the region passed as an argument. Note how by using the tuples this becomes almost trivial. The middle section of the function just waits for the specified duration time in seconds. This is implemented with a call to time.sleep(), which just halts the script for the requested time. The final section of the function sets the three LEDs for the chosen region back to (0, 0, 0) to turn them off.

After you enter the above code in your editor, click the Save button. A file dialog will open on the disk that belongs to the board. Select the name code.py for your file and save it.

Now click on the serial console in the bottom part of the Mu window. If you already have a Python REPL running, you need to press Ctrl-D to exit it and allow the board to do a soft reset to see the new code. Then enter the REPL again and test the new light_region() function as follows:

Download: file
>>> from code import light_region
>>> light_region(0)
>>> light_region(1)
>>> light_region(2)
>>> light_region(3)
>>> light_region(0, 3)  # light up for 3 seconds instead of the default of 1 second!

Isn't this awesome? Now you have a high-level function that can be used to turn selected light regions just by passing the region number! This is going to simplify the task of playing a random sequence of colors, and also responding to the user input when entering the sequence.

To make the code a bit more complete, let's add a small light demo cycle. Go back to the text editor panel in Mu and enter the following at the bottom of the code, below the light_region() function:

Download: file
while True:
    light_region(0)
    light_region(1)
    light_region(2)
    light_region(3)

Save your code, and then in the Python shell session hit Ctrl-D to trigger another soft reset. Because this last bit of code was added in the global scope (or in other words, outside of any functions), it executes automatically when the board restarts, and now you have a fully self-contained application that demonstrates the light functionality of the game!

This guide was first published on Jul 24, 2019. It was last updated on Jul 24, 2019. This page (Coding the Lights) was last updated on Nov 03, 2019.