Setup
CircuitPython Libraries
The CircuitPython code begins by importing the libraries that are used.
import random import time import adafruit_imageload.bmp import audioio import audiocore import audiomp3 import board import displayio import digitalio import framebufferio import rgbmatrix
Display setup
First, any display left over from a previous code.py is released. Then, the LED matrix is initialized according to its pinout. Because we want to ensure that all 3 wheels on screen are updated at the same time, we specify auto_refresh=False
. To learn more about how to write code using the rgbmatrix module, see the dedicated guide.
displayio.release_displays() matrix = rgbmatrix.RGBMatrix( width=64, height=32, bit_depth=3, rgb_pins=[board.D6, board.D5, board.D9, board.D11, board.D10, board.D12], addr_pins=[board.A5, board.A4, board.A3, board.A2], clock_pin=board.D13, latch_pin=board.D0, output_enable_pin=board.D1) display = framebufferio.FramebufferDisplay(matrix, auto_refresh=False)
Additional definitions
The three states let us track whether each wheel is stopped, running, or braking.
shuffled
lets us take an input sequence and return a new sequence with the order of the elements randomized. This will be used to put the symbols in a different order on each wheel.
Wheel
is a class that controls the behavior of each of the 3 fruit wheels. Check out the full source code if you want to see how it works!
# Each wheel can be in one of three states: STOPPED, RUNNING, BRAKING = range(3) # Return a duplicate of the input list in a random (shuffled) order. def shuffled(seq): return sorted(seq, key=lambda _: random.random()) # The Wheel class manages the state of one wheel. "pos" is a position in # floating point coordinates, with one 1 pixel being 1 position. # The wheel also has a velocity (in positions # per tick) and a state (one of the above constants) class Wheel(displayio.TileGrid): def __init__(self, bitmap, pixel_shader): ... def step(self): """Update each wheel for one time step""" ... def kick(self, i): """Set the wheel running again, using a slight bit of randomness. The 'i' value makes sure the first wheel brakes first, the second brakes second, and the third brakes third.""" ...
Setting up the wheels
First, load the emoji bitmap into RAM memory. It is small (just a few hundred bytes), and doing this lets the display update much more fluidly than when the bitmap is in FLASH memory.
Then, create 3 wheels and put them all in a group, setting their X and Y positions so that they span the display from left to right.
Want to learn more about setting up these kinds of images, which are also known as Sprite Sheets? There's a guide for that.
# This bitmap contains the emoji we're going to use. It is assumed # to contain 20 icons, each 20x24 pixels. This fits nicely on the 64x32 # RGB matrix display. bitmap, palette = adafruit_imageload.load( "/emoji.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette) # Our fruit machine has 3 wheels, let's create them with a correct horizontal # (x) offset and arbitrary vertical (y) offset. g = displayio.Group() wheels = [] for idx in range(3): wheel = Wheel(bitmap, palette) wheel.x = idx * 22 wheel.y = -20 g.append(wheel) wheels.append(wheel) display.root_group = g
Setting up the activation switch
The switch is connected to A1, and closing it connects it to GND. By enabling a pull up, the button.value
will be False
when it is pressed and True
otherwise.
# We want a digital input to trigger the fruit machine button = digitalio.DigitalInOut(board.A1) button.switch_to_input(pull=digitalio.Pull.UP)
Setting up the background sounds
The speaker is connected to A0. Play casino-style noises in MP3 format. If you want to change the MP3, make sure you use a file with the following properties:
- 16000 or 22050 sample rate
- 1 channel (mono)
- 64kbit/s or lower MP3 CBR encoding
You might also like to have multiple different sounds, for instance to play when the lever is pulled and when the wheels stop. You can change to a different sound file by open()
ing a new file and assigning it to sample.file
. Make sure your files all match in their sample rate, channels, and encoding.
mp3file = open("/slots.mp3", "rb") sample = audiomp3.MP3Decoder(mp3file) speaker = audioio.AudioOut(board.A0) speaker.play(sample, loop=True)
Main loop
Here's how the main loop runs:
- Refresh the screen each time through the loop
- If all the wheels are stopped, then wait for the lever to be pulled (check
button.value
) and when it is, set all the wheels in motion bykick()
ing them - Otherwise, let each wheel rotate a little bit by calling
step()
- Go back to the top of the loop
while True: # Refresh the dislpay (doing this manually ensures the wheels move # together, not at different times) display.refresh(minimum_frames_per_second=0, target_frames_per_second=60) all_stopped = all(si.state == STOPPED for si in wheels) if all_stopped: # Once everything comes to a stop, wait until the lever is pulled and # start everything over again. Maybe you want to check if the # combination is a "winner" and add a light show or something. while button.value: pass for idx, si in enumerate(wheels): si.kick(idx) # Otherwise, let the wheels keep spinning... for idx, si in enumerate(wheels): si.step()
Text editor powered by tinymce.