|
| 1 | +import time |
| 2 | +import random |
| 3 | +import board |
| 4 | +import pwmio |
| 5 | +import displayio |
| 6 | +import adafruit_imageload |
| 7 | +from audiocore import WaveFile |
| 8 | +from audioio import AudioOut |
| 9 | +from adafruit_motor import servo |
| 10 | +from digitalio import DigitalInOut, Direction, Pull |
| 11 | +from adafruit_matrixportal.matrix import Matrix |
| 12 | + |
| 13 | +# setup for down button on matrixportal |
| 14 | +switch = DigitalInOut(board.BUTTON_DOWN) |
| 15 | +switch.direction = Direction.INPUT |
| 16 | +switch.pull = Pull.UP |
| 17 | + |
| 18 | +# setup for break beam sensor |
| 19 | +break_beam = DigitalInOut(board.A1) |
| 20 | +break_beam.direction = Direction.INPUT |
| 21 | +break_beam.pull = Pull.UP |
| 22 | + |
| 23 | +# pwm for servo |
| 24 | +servo_pwm = pwmio.PWMOut(board.A4, duty_cycle=2 ** 15, frequency=50) |
| 25 | + |
| 26 | +# servo setup |
| 27 | +servo = servo.Servo(servo_pwm) |
| 28 | +servo.angle = 90 |
| 29 | + |
| 30 | +# import dreidel song audio file |
| 31 | +wave_file = open("dreidel_song.wav", "rb") |
| 32 | +wave = WaveFile(wave_file) |
| 33 | + |
| 34 | +# setup for audio out |
| 35 | +audio = AudioOut(board.A0) |
| 36 | + |
| 37 | +# setup for matrix display |
| 38 | +matrix = Matrix(width=32, height=32) |
| 39 | +display = matrix.display |
| 40 | + |
| 41 | +group = displayio.Group() |
| 42 | + |
| 43 | +# import dreidel bitmap |
| 44 | +dreidel_bit, dreidel_pal = adafruit_imageload.load("/dreidel.bmp", |
| 45 | + bitmap=displayio.Bitmap, |
| 46 | + palette=displayio.Palette) |
| 47 | + |
| 48 | +dreidel_grid = displayio.TileGrid(dreidel_bit, pixel_shader=dreidel_pal, |
| 49 | + width=1, height=1, |
| 50 | + tile_height=32, tile_width=32, |
| 51 | + default_tile=0, |
| 52 | + x=0, y=0) |
| 53 | + |
| 54 | +group.append(dreidel_grid) |
| 55 | + |
| 56 | +# show dreidel bitmap |
| 57 | +display.show(group) |
| 58 | + |
| 59 | +timer = 0 # time.monotonic() holder |
| 60 | +spin = 0 # index for tilegrid |
| 61 | +speed = 0.1 # rate that bitmap updates |
| 62 | +clock = 0 # initial time.monotonic() holder to act as time keeper |
| 63 | +gimel = 3 # bitmap index for gimel, the winning character |
| 64 | +countdown = 5 # countdown for length of game. default is 5 seconds |
| 65 | +beam_state = False # state machine for break beam |
| 66 | +reset = False # state for reset of game |
| 67 | +dreidel = False # state to track if dreidel game is running |
| 68 | + |
| 69 | +clock = time.monotonic() # initial time.monotonic() |
| 70 | + |
| 71 | +while True: |
| 72 | + # debouncing for break beam sensor |
| 73 | + if not break_beam.value and not beam_state: |
| 74 | + beam_state = True |
| 75 | + |
| 76 | + # if the break beam sensor is triggered or the down button is pressed... |
| 77 | + if (not break_beam.value and beam_state) or not switch.value: |
| 78 | + # update break beam state |
| 79 | + beam_state = False |
| 80 | + # begin reset for game states |
| 81 | + reset = True |
| 82 | + print("pressed") |
| 83 | + # quick delay |
| 84 | + time.sleep(0.1) |
| 85 | + |
| 86 | + # if reset state... |
| 87 | + if reset: |
| 88 | + # hold time.monotonic() value |
| 89 | + clock = time.monotonic() |
| 90 | + # reset countdown |
| 91 | + countdown = 5 |
| 92 | + # choose random side of dreidel to begin spinning on |
| 93 | + spin = random.randint(0, 3) |
| 94 | + # choose random speed spin the dreidel |
| 95 | + speed = random.uniform(0.05, 0.1) |
| 96 | + # set game state to True |
| 97 | + dreidel = True |
| 98 | + # turn off reset state |
| 99 | + reset = False |
| 100 | + |
| 101 | + # if the game is running... |
| 102 | + if dreidel: |
| 103 | + # play the dreidel song |
| 104 | + audio.play(wave) |
| 105 | + |
| 106 | + # while the dreidel song is playing... |
| 107 | + while audio.playing: |
| 108 | + # if more time has passed than the random delay setup in reset... |
| 109 | + if (timer + speed) < time.monotonic(): |
| 110 | + # dreidel grid index is set to spin value |
| 111 | + dreidel_grid[0] = spin |
| 112 | + # spin is increased by 1 |
| 113 | + spin += 1 |
| 114 | + # timer is updated to current time |
| 115 | + timer = time.monotonic() |
| 116 | + |
| 117 | + # if a second has passed... |
| 118 | + if time.monotonic() > (clock + 1): |
| 119 | + print(clock) |
| 120 | + print(spin) |
| 121 | + # the delay is increased to slow down the dreidel |
| 122 | + speed += 0.05 |
| 123 | + # clock is set to current time |
| 124 | + clock = time.monotonic() |
| 125 | + # countdown value is decreased by 1 |
| 126 | + countdown -= 1 |
| 127 | + |
| 128 | + # if countdown is 0 aka 5 seconds has passed since the start of game... |
| 129 | + if countdown == 0: |
| 130 | + # if the bitmap is showing gimel... |
| 131 | + # you win! |
| 132 | + if spin is gimel: |
| 133 | + # the servo turns 90 degrees to dump out chocolate coins |
| 134 | + servo.angle = 0 |
| 135 | + # 2 second delay |
| 136 | + time.sleep(2) |
| 137 | + # servo turns back to default position |
| 138 | + for i in range(0, 90, 2): |
| 139 | + servo.angle = i |
| 140 | + time.sleep(0.1) |
| 141 | + # ensures servo is in default position |
| 142 | + servo.angle = 90 |
| 143 | + # stop playing the dreidel song |
| 144 | + audio.stop() |
| 145 | + # game state is turned off |
| 146 | + dreidel = False |
| 147 | + |
| 148 | + # if you didn't win... |
| 149 | + else: |
| 150 | + # the dreidel song stops |
| 151 | + audio.stop() |
| 152 | + # game state is turned off |
| 153 | + dreidel = False |
| 154 | + |
| 155 | + # if you are at the end of the sprite sheet... |
| 156 | + if spin > 3: |
| 157 | + # index is reset to 0 |
| 158 | + spin = 0 |
0 commit comments