# Model: gemini-1.5-pro-latest
# Prompt: Generate a class called SpinGame in MicroPython that uses the classes Button, LCDDisplay, PassiveBuzzer, PrizeBox and Wheel in the files attached here. The passivebuzzer is connected to pin 16 and the button is connected to pin 15. Add buttonPressed and buttonReleased methods in the SpinGame class. When the button is pressed, use the Wheel class to show the animation and use the returned slot to report to the player what prize they won. Use a run method to start the game.
import time
from machine import Pin
from Button import Button
from Displays import LCDDisplay
from Buzzer import PassiveBuzzer, tones
from PrizeBox import PrizeBox
from Wheel import Wheel
class SpinGame:
"""
A prize wheel game that integrates a button, an LCD display, a buzzer,
and a NeoPixel wheel to create an interactive experience.
"""
# Hardware Configuration
BUTTON_PIN = 15
BUZZER_PIN = 16
# Game Configuration
WHEEL_SIZE = 16 # Must match the number of LEDs on the physical ring
def __init__(self):
"""
Initializes all the hardware and game components.
"""
print("Initializing SpinGame components...")
# Initialize hardware components
# The LCDDisplay will use default I2C pins (SDA=0, SCL=1)
self.display = LCDDisplay(sda=0, scl=1)
self.buzzer = PassiveBuzzer(self.BUZZER_PIN, name="GameBuzzer")
# The Button handler is set to 'self' to call this class's
# buttonPressed and buttonReleased methods.
self.button = Button(self.BUTTON_PIN, "SpinButton", handler=self)
# Initialize game logic components
self.wheel = Wheel(self.WHEEL_SIZE)
self.prize_box = PrizeBox(self.WHEEL_SIZE)
# Game state variable
self._is_spinning = False
print("SpinGame ready.")
def buttonPressed(self, name):
"""
Handles the event when the spin button is pressed.
This method is called automatically by the Button class's IRQ.
"""
# Prevent starting a new spin if one is already in progress
if self._is_spinning:
print("Button pressed, but already spinning. Ignoring.")
return
print(f"Button '{name}' pressed. Starting spin...")
self._is_spinning = True
# --- Start the Spin Sequence ---
self.display.clear()
self.display.showText("Spinning...", 0, 2)
self.display.showText("Good luck!", 1, 3)
self._play_spinning_sound()
# Run the wheel animation. This is a blocking call.
winning_slot = self.wheel.spin()
# --- Handle the Result ---
self._show_result(winning_slot)
def buttonReleased(self, name):
"""
Handles the event when the spin button is released.
Currently, no action is needed on release.
"""
# This method is required by the Button handler but is not used in this game logic.
# print(f"Button '{name}' released.")
pass
def _show_result(self, slot):
"""
Private method to display the prize result on the LCD and play a sound.
Args:
slot (int): The winning slot index returned by the Wheel.
"""
prize = self.prize_box.getPrize(slot)
print(f"Wheel landed on slot {slot}. Prize: {prize.type}, Value: {prize.value}")
self.display.clear()
self.display.showText(f"Landed on {slot}!", 0, 1)
if prize.type == "dollar":
self.display.showText(f"You won ${prize.value}!", 1, 1)
self._play_win_sound()
elif prize.type == "retry":
self.display.showText("Spin Again!", 1, 2)
self._play_retry_sound()
else: # "no prize"
self.display.showText("Sorry, no prize", 1, 0)
self._play_lose_sound()
# Pause to let the player see the result
time.sleep(4)
# Reset for the next round
self.display.clear()
self.display.showText("Press to Spin!", 0, 1)
self._is_spinning = False
def _play_spinning_sound(self):
""" Plays a simple sound to indicate the wheel is spinning. """
for _ in range(5):
self.buzzer.beep(tone=800, duration=50)
time.sleep(0.05)
def _play_win_sound(self):
""" Plays a happy, ascending melody for a win. """
notes = [tones['C5'], tones['E5'], tones['G5'], tones['C6']]
for note in notes:
self.buzzer.beep(tone=note, duration=100)
time.sleep(0.05)
def _play_lose_sound(self):
""" Plays a sad, descending tone for a loss. """
notes = [tones['G4'], tones['E4'], tones['C4']]
for note in notes:
self.buzzer.beep(tone=note, duration=150)
time.sleep(0.05)
def _play_retry_sound(self):
""" Plays a neutral two-tone sound for a retry. """
self.buzzer.beep(tone=tones['C5'], duration=150)
time.sleep(0.1)
self.buzzer.beep(tone=tones['G5'], duration=150)
def run(self):
"""
Starts the game. Prepares the prize box, displays a welcome message,
and enters an infinite loop to wait for button presses.
"""
# Prepare a new set of random prizes for this game session
self.prize_box.pickPrizes()
# Display initial welcome message
self.display.clear()
self.display.showText("Prize Wheel Game", 0, 0)
self.display.showText("Press to Spin!", 1, 1)
# Play a startup sound
self.buzzer.beep(tones['C4'], 100)
self.buzzer.beep(tones['G4'], 100)
self.buzzer.beep(tones['C5'], 150)
print("\nGame started. Waiting for button press...")
# The main loop keeps the program alive.
# The button's interrupt handler will trigger the game logic.
while True:
# The game is event-driven, so the main loop can be simple.
time.sleep(1)
if __name__ == '__main__':
try:
# Create an instance of the game
game = SpinGame()
# Start the game's main loop
game.run()
except Exception as e:
print(f"An error occurred: {e}")
# In a real scenario, you might want to add cleanup code here,
# like turning off the display or buzzer.
# For example:
# if 'game' in locals() and hasattr(game, 'display'):
# game.display.clear()
# if 'game' in locals() and hasattr(game, 'wheel'):
# game.wheel.strip.off()