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