You're a human! Right? For now anyway... There's a red pulsing in the distance... OH NO! IT'S A ZOMBIE! You're losing health, but what's this? A white pulsing from around a corner, a healer! You'll stay human for a little longer... Hopefully long enough to check out this guide!

Using Circuit Playground Express you can make a game that's half laser-tag half hide-and-seek. 

This game requires at least three players, which means it requires at least three Circuit Playground Expresses. You can play with as many more than three, as many as you want!

It's great for workshops, classrooms, camps or other groups of 3 or more! The more people you have, the more fun the game gets.

This guide will go through the code for the game, explain how it works and how to play. Good luck and have fun!

Parts List

For EACH player, you'll need  a Circuit Playground Express, portable power pack and a way to attach the CPX to the front of a players shirt

Circuit Playground Express

PRODUCT ID: 3333
Circuit Playground Express is the next step towards a perfect introduction to electronics and programming. We've taken the original Circuit Playground Classic and...
$24.95
IN STOCK

Portable Power

3 x AAA Battery Holder with On/Off Switch, JST, and Belt Clip

PRODUCT ID: 3286
This battery holder connects 3 AAA batteries together in series for powering all kinds of projects. We spec'd these out because the box is slim, and 3 AAA's add up to about...
OUT OF STOCK

OR

3 x AAA Battery Holder with On/Off Switch and 2-Pin JST

PRODUCT ID: 727
This battery holder connects 3 AAA batteries together in series for powering all kinds of projects. We spec'd these out because the box is slim, and 3 AAA's add up to about...
OUT OF STOCK

Circuit Playground Attachment

Silver Pin Back with Foam Adhesive

PRODUCT ID: 2838
This little Silver-color Pin with Foam Adhesive is the perfect way to attach any PCB or small component to cloth material. The adhesive forms a solid but...
$0.45
IN STOCK

OR

Magnetic Pin Back

PRODUCT ID: 1170
These magnetic pin backs have two pieces: a metal bar with adhesive strip and a plastic piece with two strong rare-earth magnets. Affix the metal bar to your FLORA projects-- it's...
$1.95
IN STOCK

OR use some safety pins!

Zombie Game Time!

We've written up a fun game of zombie tag for you to use with Circuit Playground Express (CPX).

It uses infrared signals to communicate between CPXs.

You can be human, a zombie or a healer.

The human is affected by zombies and healers. If a human comes into contact with a zombie, they start to lose health points. That's where the healer comes in.

If a human comes into contact with a healer, they regain health points. The goal is to maintain at least one health point.

If a human loses all health, they become a zombie too! And zombies can't return to being humans. But, they can start attacking other humans! So, run when you see them!

The game starts with at least one healer, at least one zombie, and the rest of the players are humans. If you have a large group, try having 2 or 3 zombies. This game works great in a large room or outdoors, as long as people can run around and hide.

The Characters

HUMAN - Try not to lose all of your health points.

ZOMBIE - Slowly reduces human health by 1 point.

 

Goal: Turn all humans into Zombies

HEALER - Quickly restores human health by 1 point.

 

Goal: Find humans that are low on health and heal them up!

Each board lights up a different color to identify the role. Humans are solid green, healers slowly pulse white, and zombies quickly pulse red.

The healer and zombie boards emit different IR signals. The human board waits to receive these signals.

When a zombie signal is received, the human loses one health point.

When a healer signal is received, the human regains one health point.

The current number of health points for the human are shown by the NeoPixels lit up.

CircuitPython Zombies

If you are new to CircuitPython, be sure to check out the Welcome guide for an overview. And if you want to know even more, check out the Essentials guide.

Ensure your Circuit Playground Express has CircuitPython 3.0 or later.

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in      CircuitPython. You can learn about Mu and installation in this tutorial.

In the CircuitPython version, you can select what you want to be when the board is powered up. To be a human, simply start up the board. To be a healer, hold down button A while first running the program. To be a zombie, hold down button B while first running the program.

Copy the following to code.py on at least three Circuit Playground Expresses:

import time
import pulseio
import board
import adafruit_irremote
import digitalio
import neopixel

pixels = neopixel.NeoPixel(board.NEOPIXEL, 10)

button_a = digitalio.DigitalInOut(board.BUTTON_A)
button_a.switch_to_input(pull=digitalio.Pull.DOWN)

button_b = digitalio.DigitalInOut(board.BUTTON_B)
button_b.switch_to_input(pull=digitalio.Pull.DOWN)

red_led = digitalio.DigitalInOut(board.D13)
red_led.direction = digitalio.Direction.OUTPUT

# Create a 'pulseio' input, to listen to infrared signals on the IR receiver
pulsein = pulseio.PulseIn(board.IR_RX, maxlen=120, idle_state=True)
# Create a decoder that will take pulses and turn them into numbers
decoder = adafruit_irremote.GenericDecode()

# Create a 'pulseio' output, to send infrared signals on the IR transmitter @ 38KHz
pwm = pulseio.PWMOut(board.IR_TX, frequency=38000, duty_cycle=2 ** 15)
pulseout = pulseio.PulseOut(pwm)
# Create an encoder that will take numbers and turn them into NEC IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500], one=[550, 550],
                                            zero=[550, 1700], trail=0)

# Set between 0 and 1 to set LED pulse speed. Smaller numbers are slower.
healer_led_pulse = 0.008
zombie_led_pulse = 0.07
pixels.brightness = 0.0

# Change to set number of seconds between each signal being sent.
HEALER_TIME = 1
ZOMBIE_TIME = 3

# The Healer and Zombie IR signal codes
HEALER_IR = [72, 69, 65, 76]
ZOMBIE_IR = [90, 79, 77, 66]

human_health_counter = 10
human = 0
healer = 1
zombie = 2

if button_a.value:  # Hold button A down before starting up to set mode Healer.
    mode = healer
    pixels.fill((255, 255, 255))
    pixels.brightness = 0.3
elif button_b.value:  # Hold button A down before starting up to set mode Zombie.
    mode = zombie
    pixels.fill((255, 0, 0))
    pixels.brightness = 0.8
else:  # Defaults to human mode!
    mode = human
    pixels.fill((0, 255, 0))
    pixels.brightness = 0.5

start = time.monotonic()
while True:
    now = time.monotonic()
    if mode is human:
        pulses = decoder.read_pulses(pulsein)
        try:
            # Attempt to convert received pulses into numbers
            received_code = decoder.decode_bits(pulses)
        except adafruit_irremote.IRNECRepeatException:
            # We got an unusual short code, probably a 'repeat' signal
            continue
        except adafruit_irremote.IRDecodeException:
            # Something got distorted or maybe its not an NEC-type remote?
            continue
        print("NEC Infrared code received: ", received_code)
        if received_code == ZOMBIE_IR:
            print("Zombie code received!")
            pixels.fill(0)
            human_health_counter -= 1
            for i in range(human_health_counter):
                pixels[i] = (0, 255, 0)
            if human_health_counter < 1:
                mode = zombie
                pixels.fill((255, 0, 0))
                print("Zombified!")
        if received_code == HEALER_IR:
            print("Healer code received!")
            if human_health_counter < 10:
                pixels.fill(0)
                human_health_counter += 1
                for i in range(human_health_counter):
                    pixels[i] = (0, 255, 0)
            else:
                pass
    elif mode is zombie:
        brightness = pixels.brightness
        brightness += zombie_led_pulse
        if not 0.0 <= brightness <= 1.0:
            zombie_led_pulse = -zombie_led_pulse
            continue
        pixels.brightness = brightness
        if now - start > ZOMBIE_TIME:
            print("Zombie code sent! \n")
            red_led.value = True
            encoder.transmit(pulseout, ZOMBIE_IR)
            red_led.value = False
            start = time.monotonic()
    elif mode is healer:
        brightness = pixels.brightness
        brightness += healer_led_pulse
        if not 0.0 <= brightness <= 0.5:
            healer_led_pulse = -healer_led_pulse
            continue
        pixels.brightness = brightness
        if now - start > HEALER_TIME:
            print("Healer code sent! \n")
            red_led.value = True
            encoder.transmit(pulseout, HEALER_IR)
            red_led.value = False
            start = time.monotonic()

Healer

Let's start with the healer. To choose the healer role, you'll hold down button A while the program starts up. This means you can hold button A before you provide power to the board and let it start up while holding the button. You can also hold the button and then reset the board while continuing to hold the button. When the role is successfully chosen, the LEDs will be white.

The healer lights up and slowly pulses the LEDs white. Every second, the healer transmits an IR signal. The little red LED lights up to let you know the signal is being sent.

The signal interval is configurable in the code - you can change HEALER_TIME = 1 to a different number of seconds. Increase the number to send the signal less often and make the game more difficult. Decrease the number to send the signal more often and make the game easier.

That's all there is to the healer. Healers are not affected by humans or zombies.

Zombie

Next, we'll look at the zombie. To choose the zombie role, you'll hold down button B while the program starts up. This works the same way as choosing the healer role. You can hold the button down and during powering on the board, or you can hold it down and reset the board while continuing to hold it. When the role is successfully chosen, the LEDs will be red.

The zombie lights up and quickly pulses the LEDs red. Every three seconds, the zombie transmits an IR signal. The little red LED lights up to let you know the signal is being sent.

The signal interval is configurable in the code - you can change ZOMBIE_TIME = 3 to a different number of seconds. As with the healer, increase the number to send the signal less often and decrease it to send it more often.

That's all there is to the zombie. Zombies are not affected by humans or healers.

Human

Finally, we'll look at the human. To choose the human role, all you have to do is start up the board. The code defaults to the human role. When the role is successfully chosen, the LEDs will be green.

The human lights up solid green. The human starts with 10 health points, as indicated by 10 green LEDs. Humans are affected by both healers and zombies. The human waits to receive signals from the healer and zombie.

When the zombie signal is received, the human will lose a health point, and one green LED will shut off. This will continue every time a zombie signal is received.

If the human cannot find a healer, they'll continue to lose health points until they have 0. When this happens, the human will turn into a zombie. Zombies can't return to being human. At that point, they'll start transmitting the zombie signal which can affect any other humans still in the game.

When a healer signal is received, the human will regain one health point, and the last green LED will turn back on. As long as the human is receiving the healer signal, they will continue to regain health points, and the green LEDs will turn back on until the human is at full health.

Time To Play!

Now it's time to load the code on as many boards as you can find, start them up into the role you'd like to play, and start running! Good luck!

MakeCode Zombies

If you haven't used MakeCode before, then check out the following guide:

For the MakeCode version, there are three separate programs. You choose what you want to be by loading the appropriate version. We'll go over each below, starting with the Zombie and Healer, since they are very similar and the most simple.

Zombie

Here's the link to the Zombie MakeCode:

There are only thee main chunks. The first is the on start block, which just sets the initial values for some variables and turns all the NeoPixels to Zombie Red.

The Zombie needs to send out the Zombie code every now and then to try and attack the Humans. This is done with a forever loop. Pretty simple - it sends out the code and then sleeps for the amount of time set by ZOMBIE_TIME. Then does it again - over and over, forever.

The other forever loop is used to create the pulsing effect on the NeoPixels. This is done by changing the value of brightness up and down over and over again.

And that's it. Now let's look at the Healer.

Healer

Here's the link to the Healer MakeCode:

The Healer is pretty much the same thing as the Zombie. It is simply altered to send out a different IR code and at a different rate, have different color NeoPixels, and pulse at a slower rate.

Now for those Humans.

Human

Here's the link to the Human MakeCode:

Oof. This one has a lot going on. It doesn't even fit on one screen! But hey, humans are complex. We can still go through it chunk by chunk.

It all starts with the familiar on start, which again just initializes a bunch of variables to be used by the program.

With the Zombie and Healer, we were transmitting IR signals. For the Human, we need to receive those signals and process them. That is done using the on infrared received block. The value of received_code is checked and the value of health_counter is either decreased or increased, depending on if the code is from a Zombie or a Healer.

The value of health_counter is then checked. We limit it to a max of 10. But more importantly, we check to see if it has reached 0. If so, the Human is turned into a Zombie.

The rest of the code is split amongst several forever loops. The first one checks to see if the CPX is still Human. If so, it updates the NeoPixels to indicate the current amount of health left.

The next forever loop kicks in when the CPX becomes a Zombie. It should look similar to the one you saw in the Zombie program. This is what sends out the Zombie code on the IR transmitter. The difference here is we add a check to only do this when the board actually is a Zombie. Therefore, this does not happen when the board is still a Human.

The last forever loop is what pulses the NeoPixels when the board becomes a Zombie. It is also just the same thing from the Zombie code, but again with a check to only run when the board actually becomes a Zombie.

And that's it. It looks like a lot, and it kinda is. Hopefully it helps to try and just think in terms of the large chunks described above. Like the big chunk that "receives the IR signal" and the big chunk that "pulses the NeoPixels". Then it becomes easier to see how these big chunks fit together to make the program work. After that, you can look at the chunks in more detail to try and understand how they are actually achieving that.

OK. Enough discussion. Gather up some friends and some Circuit Playground Express boards. Load up the programs. And have fun.

rrrrrrrrrrrr.....brains.......

Make It Wearable

To be able to run around and play the Zombie Game you'll need some way to battery power the Circuit Playground Express. You'll also want some way to attach the Circuit Playground Express board to the outside of your clothing.

For battery power, this 3xAAA battery pack is a good choice. It has an On/Off switch and a nice little belt clip you can use for attaching to clothing. The JST connector plugs right into the Circuit Playground Express.

3 x AAA Battery Holder with On/Off Switch, JST, and Belt Clip

PRODUCT ID: 3286
This battery holder connects 3 AAA batteries together in series for powering all kinds of projects. We spec'd these out because the box is slim, and 3 AAA's add up to about...
OUT OF STOCK

For actually attaching the Circuit Playground Express, there are various options. This stick pin is one way, but you will need to be careful with the sharp pointy pin.

Silver Pin Back with Foam Adhesive

PRODUCT ID: 2838
This little Silver-color Pin with Foam Adhesive is the perfect way to attach any PCB or small component to cloth material. The adhesive forms a solid but...
$0.45
IN STOCK

Attaching it to the board is pretty easy.

Remove the backing and stick the pin to the back of the Circuit Playground Express.

Ready for action!

(but be careful of the sharp pointy pin)

Another option is this magnetic holder. It doesn't have any sharp pointy things, but you'll need to be able to put the other side of the holder inside the clothing somehow.

Magnetic Pin Back

PRODUCT ID: 1170
These magnetic pin backs have two pieces: a metal bar with adhesive strip and a plastic piece with two strong rare-earth magnets. Affix the metal bar to your FLORA projects-- it's...
$1.95
IN STOCK

Mounting it is similar to the other pin back.

Remove the backing and stick the one side of the magnet to the back of the Circuit Playground Express.

Ready for action!

Pockets also make for convenient battery storage if you can't find a place to clip the battery pack.

OH NO! Losing health! Need to find a Healer fast!

This guide was first published on Jul 31, 2018. It was last updated on Jul 31, 2018.