#
# Model: gemini-pro
# Task:
# Create a MicroPython class named SpinGame that integrates the modules Button,
# LCDDisplay, PassiveBuzzer, PrizeBox, and Wheel from the provided files.
# The PassiveBuzzer should be wired to GPIO pin GP3, and the Button should be linked to GP16.
# Include methods called ButtonPressed and ButtonReleased within the SpinGame class to trigger
# the visual effect and use the resulting slot to inform the user of the prize they've earned.
# Implement a run method to initiate the gameplay.
#
import utime
from Button import Button
from Displays import LCDDisplay
from Buzzer import PassiveBuzzer, tones
from PrizeBox import PrizeBox
from Wheel import Wheel
from Log import Log
# --- Hardware Configuration ---
# Match the wheel size to the number of LEDs on your NeoPixel ring
WHEEL_SIZE = 8
BUTTON_PIN = 15
BUZZER_PIN = 3
# Standard I2C pins for Raspberry Pi Pico (I2C bus 0)
LCD_SDA_PIN = 0
LCD_SCL_PIN = 1
class SpinGame:
"""
Controls the prize wheel game and coordinates all hardware modules.
"""
def __init__(self):
"""
Sets up the game components and initializes the system state.
"""
Log.i("Booting up SpinGame...")
# --- Hardware Setup ---
self.display = LCDDisplay(sda=LCD_SDA_PIN, scl=LCD_SCL_PIN)
self.buzzer = PassiveBuzzer(BUZZER_PIN, name="GameBuzzer")
self.wheel = Wheel(size=WHEEL_SIZE)
self.prize_box = PrizeBox(size=WHEEL_SIZE)
# Assign this class as the handler for button events.
# When pressed, it triggers self.buttonPressed()
self.button = Button(BUTTON_PIN, "SpinButton", handler=self)
# --- Internal State ---
self._spinning = False
self._running = False
Log.i("SpinGame setup complete.")
def _play_startup_sound(self):
"""Plays a quick melody to signal that the game is ready."""
self.buzzer.beep(tones['C4'], 100)
self.buzzer.beep(tones['E4'], 100)
self.buzzer.beep(tones['G4'], 100)
def _display_welcome_message(self):
"""Displays the welcome screen on the LCD."""
self.display.clear()
self.display.showText("Spin The Wheel!", row=0, col=1)
self.display.showText("Press to Play...", row=1, col=0)
def buttonPressed(self, name):
"""
Responds to button press events. This method drives the main game loop.
It's automatically triggered by the Button class's interrupt.
"""
# Prevent multiple spins from overlapping
if self._spinning:
Log.i("Button press ignored—wheel already spinning.")
return
self._spinning = True
Log.i("Initiating spin sequence...")
# --- Phase 1: Spin the Wheel ---
self.display.clear()
self.display.showText("Spinning...", row=0, col=2)
# Play sound during spin animation
self.buzzer.play(tones['C3'])
# Blocking call: runs LED animation and returns final slot
winning_slot = self.wheel.spin()
self.buzzer.stop() # End spin sound
# --- Phase 2: Reveal the Prize ---
prize = self.prize_box.getPrize(winning_slot)
Log.i(f"Prize awarded: {prize}")
self.display.clear()
if prize.type == "dollar":
self.display.showText("YOU WON!", row=0, col=4)
self.display.showText(f"${prize.value}", row=1, col=6)
# Play celebratory tones
self.buzzer.beep(tones['C5'], 150)
self.buzzer.beep(tones['G5'], 300)
elif prize.type == "retry":
self.display.showText("SO CLOSE!", row=0, col=3)
self.display.showText("Spin Again!", row=1, col=2)
self.buzzer.beep(tones['E4'], 150)
self.buzzer.beep(tones['E4'], 150)
else: # No prize won
self.display.showText("Sorry!", row=0, col=4)
self.display.showText("No Prize", row=1, col=3)
# Play consolation sound
self.buzzer.beep(tones['C3'], 400)
# --- Phase 3: Reset for Next Round ---
utime.sleep(3) # Pause to let player see result
self.prize_box.PickPrizes() # Refresh prize slots
self._display_welcome_message() # Show welcome again
self._spinning = False # Ready for next input
Log.i("System reset—awaiting next spin.")
def buttonReleased(self, name):
"""
Required by the Button class, but no action is needed when released.
"""
pass
def run(self):
"""
Launches the game, shows welcome message, and enters the main loop.
"""
self._running = True
self.display.clear()
self._play_startup_sound()
self._display_welcome_message()
self.prize_box.PickPrizes() # Initialize prize list
Log.i("Game active. Awaiting user input...")
try:
# Main loop remains idle; button press is handled via interrupt
while self._running:
utime.sleep(1)
except KeyboardInterrupt:
self._cleanup()
def _cleanup(self):
"""Safely powers down all connected components."""
Log.i("Shutting down system.")
self._running = False
self.display.clear()
self.display.showText("Goodbye!", row=0, col=4)
self.wheel.strip.off()
self.buzzer.stop()
self.button.setHandler(None) # Remove button event handler
if __name__ == "__main__":
game = SpinGame()
game.run()