[fix] Small errors

- Ball can no longer lock to paddle
- Brick edges are part of the brick
This commit is contained in:
2025-04-03 22:00:57 +02:00
parent aa96f89a13
commit 0e5b5f67fa
4 changed files with 112 additions and 40 deletions
+21
View File
@@ -0,0 +1,21 @@
# Program Documentation
## Overview
This program is a simple game implemented in MicroPython for the Raspberry Pi Pico with a Pico-LCD-1.14 display. The game involves controlling a character to avoid obstacles and score points. The program includes a splash screen, game over screen, and a main game loop.
## Framebuffer
The program use framebuffer to draw the game graphics. The framebuffer is a 2D array that represents the pixels on the display. The program uses the `framebuf` module to create and manipulate the framebuffer. The framebuffer is then copied to the display using the `blit` method.
## Multithreading
The program uses multithreading to handle the game logic and the display updates separately. The `threading` module is used to create and manage the threads. The game logic is run in a separate thread from the display updates to ensure smooth gameplay and responsive controls.
## Game Logic
The game logic is implemented in the `game_loop` function. This function runs in a separate thread and handles the following tasks:
- Updating the game state based on user input and game rules
- Generating new obstacles and updating their positions
- Checking for collisions between the character and obstacles
- Updating the score based on the player's performance
- Sending the updated game state to the display thread for rendering
+32
View File
@@ -0,0 +1,32 @@
# Breakout Game for Raspberry Pi Pico
This is a simple Breakout game implemented in MicroPython for the Raspberry Pi Pico. The game uses the Pico-LCD-1.14 dDisplay for graphics and input.
## Features
- Classic Breakout gameplay
- Simple and intuitive controls
- Basic collision detection
- Score tracking
- Splash screen and game over screens
## Requirements
- Raspberry Pi Pico
- Pico-LCD-1.14 display
- MicroPython firmware installed on the Pico
## Installation and Setup
1. Connect the Pico-LCD-1.14 display to the Raspberry Pi Pico following the wiring diagram provided in the display's documentation.
2. Download the MicroPython firmware for the Raspberry Pi Pico from the official MicroPython website and install it on the Pico. You can use the Thonny IDE to upload the firmware.
3. Clone or download this repository to your local machine.
4. Open the Thonny IDE and connect to your Raspberry Pi Pico.
5. Copy the contents of the repository to the Pico's file system. You can do this by dragging and dropping the files from your local machine to the Thonny file explorer.
6. Once the files are copied, reset the Pico to start the game.
+14
View File
@@ -0,0 +1,14 @@
{
"folders": [
{
"path": "."
},
{
"name": "Mpy Remote Workspace",
"uri": "pico:"
}
],
"settings": {
"python.languageServer": "Pylance"
}
}
+45 -40
View File
@@ -136,10 +136,15 @@ class Paddle:
self.draw()
def hit(self, ball: Ball) -> bool:
"""Check if the ball hits the paddle."""
return (
self.x < ball.x < self.x + self.width
and self.y < ball.y < self.y + self.height)
"""Check if the ball hits the paddle and adjust its position."""
if (
self.x <= ball.x <= self.x + self.width
and self.y <= ball.y + ball.radius <= self.y + self.height
):
# Adjust the ball's position to be just above the paddle
ball.y = self.y - ball.radius - 2
return True
return False
class Ball:
@@ -163,11 +168,11 @@ class Ball:
self.y = paddle.y - radius - 2 # Place the ball just above the paddle
def reset_pos(self, paddle: Paddle):
"""Reset ball position to the center of the screen.
"""Reset ball position to the center of the paddle.
Args: Paddle: The paddle object to position the ball on.
"""
self.x = SCREEN_HEIGHT // 2
self.y = SCREEN_WIDTH // 2
self.y = SCREEN_WIDTH // 2 - self.radius - 2
self.x_speed = BALL_SPEED
self.y_speed = -BALL_SPEED
@@ -181,7 +186,7 @@ class Ball:
self.x = 0
self.x_speed = -self.x_speed
elif self.x > SCREEN_HEIGHT:
self.x = SCREEN_HEIGHT
self.x = SCREEN_HEIGHT - self.radius
self.x_speed = -self.x_speed
# Bounce off top screen edge
@@ -255,7 +260,7 @@ class BrickRow:
"""
for i, brick in enumerate(self.bricks):
if brick is not None:
if (brick.x < ball.x < brick.x + brick.width) and (brick.y < ball.y < brick.y + brick.height):
if (brick.x <= ball.x <= brick.x + brick.width) and (brick.y <= ball.y <= brick.y + brick.height):
# Remove the brick by setting it to None
self.bricks[i] = None
return True
@@ -299,40 +304,40 @@ def main_loop():
global fbuf, buffer, buffer_width, buffer_height, joystick
global render_frame
bricks = []
for row in range(ROWS):
if row == 0:
color = RED
elif row == 1:
color = YELLOW
else:
color = GREEN
bricks.append(
BrickRow(BRICK_WIDTH,
BRICK_HEIGHT,
BRICK_PADDING,
10 + row * (BRICK_HEIGHT + BRICK_PADDING),
color))
score = 0
lives = 3
paddle = Paddle()
ball = Ball(paddle, radius=5, color=WHITE)
# Create a list of small balls to represent lives
lives_balls = []
for i in range(0, lives):
life_ball = Ball(paddle, radius=3, color=WHITE)
life_ball.x = 5 + (i - 1) * 7
life_ball.y = 7
life_ball.x_speed = 0
lives_balls.append(life_ball)
render_frame = False
state = 0 # 0 = start screen, 1 = game, 2 = game over, 3 = game win
try:
while True:
if state == 0: # Startup screen
if state == 0: # Startup screen & init game state
bricks = []
for row in range(ROWS):
if row == 0:
color = RED
elif row == 1:
color = YELLOW
else:
color = GREEN
bricks.append(
BrickRow(BRICK_WIDTH,
BRICK_HEIGHT,
BRICK_PADDING,
10 + row * (BRICK_HEIGHT + BRICK_PADDING),
color))
score = 0
lives = 3
paddle = Paddle()
ball = Ball(paddle, radius=5, color=WHITE)
# Create a list of small balls to represent lives
lives_balls = []
for i in range(0, lives):
life_ball = Ball(paddle, radius=3, color=WHITE)
life_ball.x = 5 + (i - 1) * 7
life_ball.y = 7
life_ball.x_speed = 0
lives_balls.append(life_ball)
render_frame = False
splash_screen([0x060046, 0x056B54, 0x054A64, 0x064A46, 0x054A62, 0x054A52, 0x074B56])
if joystick.button_a() == 0: # Transition to game state when A is pressed
@@ -345,10 +350,10 @@ def main_loop():
if ball.update_pos(): # If ball is out of bounds, lose a life and reset ball position
lives -= 1
lives_balls.pop()
ball.reset_pos(paddle) # Reset ball position to the center of the screen
ball.reset_pos(paddle) # Reset ball position to the center of the paddle
if paddle.hit(ball):
ball.y_speed = -ball.y_speed
ball.y_speed = -abs(ball.y_speed)
for row in bricks:
if row.hit(ball):
ball.y_speed = -ball.y_speed