"""
Simple Pacman Game for Raspberry Pi Pico
Basic game with LCD display (I2C), 2 buttons, LED strip and buzzer
"""
from LightStrip import LightStrip
from Buzzer import PassiveBuzzer
from Button import Button
from Displays import LCDDisplay
import time
class SimplePacman:
def __init__(self):
# Initialize hardware components
self.display = LCDDisplay(sda=0, scl=1) # LCD on I2C0
self.strip = LightStrip(pin=2, numleds=8) # LED strip
self.buzzer = PassiveBuzzer(15) # Buzzer on pin 15
# Initialize buttons
self.left_btn = Button(16, "left", handler=self) # Red button
self.right_btn = Button(17, "right", handler=self) # Blue button
# Game state
self.player_pos = 0
self.ghost_pos = 15
self.score = 0
self.lives = 3
self.game_active = False
# Display initial message
self.display.clear()
self.display.showText("Press any button", 0, 0)
self.display.showText("to start!", 1, 4)
def buttonPressed(self, name):
"""Handle button press events"""
if not self.game_active:
self.start_game()
return
if name == "left" and self.player_pos > 0:
self.player_pos -= 1
self.buzzer.beep(500, 50)
elif name == "right" and self.player_pos < 15:
self.player_pos += 1
self.buzzer.beep(500, 50)
self.update_game()
def buttonReleased(self, name):
"""Handle button release events"""
pass
def start_game(self):
"""Start a new game"""
self.game_active = True
self.player_pos = 0
self.ghost_pos = 15
self.score = 0
self.lives = 3
self.update_game()
def update_game(self):
"""Update game state and display"""
# Clear display
self.display.clear()
# Show score and lives on top row
self.display.showText(f"S:{self.score} L:{self.lives}", 0, 0)
# Show player and ghost on bottom row
bottom_row = [" "] * 16
bottom_row[self.player_pos] = "P"
bottom_row[self.ghost_pos] = "G"
self.display.showText("".join(bottom_row), 1, 0)
# Update LED strip - show lives
for i in range(8):
if i < self.lives:
self.strip.setPixel(i, (255, 0, 0)) # Red for lives
else:
self.strip.setPixel(i, (0, 0, 0)) # Off
self.strip.show()
# Check for collision
self.check_collision()
def check_collision(self):
"""Check for collision between player and ghost"""
if self.player_pos == self.ghost_pos:
self.lives -= 1
self.buzzer.beep(200, 500) # Lower tone for losing a life
if self.lives <= 0:
self.game_over()
else:
# Reset positions
self.player_pos = 0
self.ghost_pos = 15
time.sleep(1)
self.update_game()
def move_ghost(self):
"""Move ghost toward player"""
if self.ghost_pos > self.player_pos:
self.ghost_pos -= 1
elif self.ghost_pos < self.player_pos:
self.ghost_pos += 1
if self.game_active:
self.update_game()
def game_over(self):
"""Handle game over state"""
self.game_active = False
self.display.clear()
self.display.showText("Game Over!", 0, 3)
self.display.showText(f"Score: {self.score}", 1, 4)
# Flash LED strip red
self.strip.setColor((255, 0, 0))
time.sleep(1)
self.strip.setColor((0, 0, 0))
# Play game over sound
self.buzzer.beep(200, 200)
time.sleep(0.2)
self.buzzer.beep(150, 400)
time.sleep(2)
# Return to start screen
self.display.clear()
self.display.showText("Press any button", 0, 0)
self.display.showText("to start!", 1, 4)
def run(self):
"""Main game loop"""
last_ghost_move = time.ticks_ms()
while True:
try:
current_time = time.ticks_ms()
# Move ghost every second if game is active
if self.game_active and (current_time - last_ghost_move) > 1000:
self.move_ghost()
last_ghost_move = current_time
# Small delay to prevent CPU overload
time.sleep(0.1)
except KeyboardInterrupt:
self.strip.off()
self.display.clear()
break
# Create and run the game
if __name__ == "__main__":
game = SimplePacman()
game.run()