当前位置: 首页 > article >正文

使用Pygame制作“打砖块”游戏

1. 前言

打砖块(Breakout / Arkanoid) 是一款经典街机游戏,玩家控制一个可左右移动的挡板,接住并反弹球,击碎屏幕上方的砖块。随着砖块被击碎,不仅能获得分数,还可以体验到不断加速或复杂的反弹乐趣。 在本篇文章里,我们将使用 Python 3.x + Pygame 库,手把手实现一个简易版本的打砖块游戏,包含最核心的移动、碰撞和得分功能。


2. 开发环境与准备

  1. Python 3.x
  2. Pygame:若尚未安装,可通过命令 pip install pygame 进行安装。
  3. 桌面系统:Windows、macOS 或绝大多数 Linux 桌面环境都能正常使用 Pygame。

安装完成后,使用 import pygame 测试是否成功即可。


3. 游戏思路

要完成一个打砖块游戏,需要实现以下几个关键模块:

  1. 挡板(Paddle)

    • 位于屏幕底部,可左右移动。
    • 通过键盘或鼠标控制位置。
  2. 球(Ball)

    • 从挡板上方出发,向上运动;
    • 在碰到墙壁时发生反弹;
    • 在碰到挡板或砖块时,需要计算反弹方向,并可能击碎砖块、加分。
  3. 砖块(Bricks)

    • 通常在屏幕上方排列成若干行;
    • 一旦被球击中,会被击碎并增加分数;
    • 也可以设定一些特殊砖块,击中后会产生道具等(此处仅做简易实现)。
  4. 游戏结束

    • 若球掉出屏幕底部则表示丢失一条命,或者直接游戏结束;
    • 如果所有砖块都被击碎,则玩家胜利。

4. 完整示例代码

将以下示例保存为 breakout_game.py 并运行,即可体验一个最基本的打砖块游戏。你也可以根据需求自由添加更多功能或美化界面。

import pygame
import sys
import random

# 初始化 Pygame
pygame.init()

# ----------------------
#  全局配置
# ----------------------
WIDTH, HEIGHT = 600, 600   # 游戏窗口大小
FPS = 60                   # 帧率

# 颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY  = (100, 100, 100)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)
YELLOW = (255, 255, 0)

# 游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("打砖块 - Pygame 示例")
clock = pygame.time.Clock()

# 字体
font = pygame.font.SysFont("arial", 24)

# ----------------------
#  挡板类
# ----------------------
class Paddle:
    def __init__(self):
        self.width = 100
        self.height = 15
        self.x = (WIDTH - self.width) // 2
        self.y = HEIGHT - 50
        self.speed = 8

    def draw(self, surface):
        pygame.draw.rect(surface, BLUE, (self.x, self.y, self.width, self.height))

    def move_left(self):
        self.x -= self.speed
        if self.x < 0:
            self.x = 0

    def move_right(self):
        self.x += self.speed
        if self.x + self.width > WIDTH:
            self.x = WIDTH - self.width

# ----------------------
#  球类
# ----------------------
class Ball:
    def __init__(self, paddle):
        self.radius = 8
        self.x = paddle.x + paddle.width // 2
        self.y = paddle.y - 10
        # 球初始速度
        self.speed_x = random.choice([-4, 4])
        self.speed_y = -4

    def draw(self, surface):
        pygame.draw.circle(surface, RED, (int(self.x), int(self.y)), self.radius)

    def update(self, paddle, bricks):
        """
        更新球的位置、检查墙体碰撞、挡板碰撞和砖块碰撞
        """
        self.x += self.speed_x
        self.y += self.speed_y

        # 碰撞左右墙
        if self.x - self.radius < 0:
            self.x = self.radius
            self.speed_x = -self.speed_x
        elif self.x + self.radius > WIDTH:
            self.x = WIDTH - self.radius
            self.speed_x = -self.speed_x

        # 碰撞上墙
        if self.y - self.radius < 0:
            self.y = self.radius
            self.speed_y = -self.speed_y

        # 掉到底部 -> 游戏结束的处理可在主循环中判断
        # if self.y + self.radius > HEIGHT:
        #    pass

        # 碰撞挡板
        if (self.x > paddle.x and self.x < paddle.x + paddle.width
                and self.y + self.radius > paddle.y
                and self.y - self.radius < paddle.y + paddle.height):
            self.speed_y = -self.speed_y
            # 球可能根据撞击位置微调水平速度(可选)
            # self.speed_x += random.choice([-1, 0, 1])

        # 碰撞砖块
        for brick in bricks[:]:
            if (self.x + self.radius > brick.x
                    and self.x - self.radius < brick.x + brick.width
                    and self.y + self.radius > brick.y
                    and self.y - self.radius < brick.y + brick.height):
                bricks.remove(brick)
                self.speed_y = -self.speed_y  # 简化反弹,只改变垂直方向
                return 10  # 得分10
        return 0

# ----------------------
#  砖块类
# ----------------------
class Brick:
    def __init__(self, x, y, width, height, color=GREEN):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color

    def draw(self, surface):
        pygame.draw.rect(surface, self.color, (self.x, self.y, self.width, self.height))
        pygame.draw.rect(surface, BLACK, (self.x, self.y, self.width, self.height), 1)  # 边框

def create_bricks(rows=5, cols=8):
    """
    创建指定行列的砖块,返回列表
    """
    bricks = []
    brick_width = (WIDTH - 40) // cols
    brick_height = 20
    x_offset = 20
    y_offset = 40
    for row in range(rows):
        for col in range(cols):
            x = x_offset + col * brick_width
            y = y_offset + row * brick_height
            color = random.choice([GREEN, YELLOW, GRAY, BLUE])
            brick = Brick(x, y, brick_width, brick_height, color)
            bricks.append(brick)
    return bricks

# ----------------------
#  主函数
# ----------------------
def main():
    paddle = Paddle()
    ball = Ball(paddle)
    bricks = create_bricks(rows=5, cols=8)
    score = 0
    running = True

    while running:
        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 键盘输入
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            paddle.move_left()
        if keys[pygame.K_RIGHT]:
            paddle.move_right()

        # 更新球的位置
        gained_score = ball.update(paddle, bricks)
        score += gained_score

        # 判断游戏结束:如果球掉到底部 or 砖块全部消失
        if ball.y - ball.radius > HEIGHT:
            # 球掉出底部
            running = False
        if len(bricks) == 0:
            # 所有砖块被击破
            running = False

        # 绘制
        screen.fill(BLACK)
        # 画砖块
        for brick in bricks:
            brick.draw(screen)
        # 画挡板和球
        paddle.draw(screen)
        ball.draw(screen)
        # 显示分数
        text_surface = font.render(f"Score: {score}", True, WHITE)
        screen.blit(text_surface, (10, 10))

        pygame.display.flip()

    # 游戏结束后显示结果
    game_over(score)

def game_over(score):
    """游戏结束界面"""
    screen.fill(GRAY)
    msg = f"Game Over! Your Score: {score}"
    label = font.render(msg, True, BLACK)
    # 居中显示
    rect = label.get_rect(center=(WIDTH // 2, HEIGHT // 2))
    screen.blit(label, rect)
    pygame.display.flip()
    pygame.time.wait(3000)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

核心逻辑解读

  1. Paddle(挡板)

    • 只需实现水平移动;
    • 在超出屏幕边界时,强制回到合法范围内。
  2. Ball(球)

    • 通过 self.x, self.y 表示球心位置,self.speed_x, self.speed_y 表示当前水平和垂直速度;
    • 每帧更新时,先加上速度;遇到左右墙、上墙时反转速度;遇到底部则表示掉落。
    • 在与挡板或砖块相交时,需要根据碰撞方向做出相应反弹。
  3. Brick(砖块)

    • 仅保存坐标、宽高、颜色;
    • 被击中后从列表中移除。
  4. 碰撞检测

    • 简化实现:只要球的圆心与砖块矩形区域重叠即可判断为碰撞;
    • 在真实游戏中,可以做更精确的检测(圆与矩形边的距离、角度等)或更细致的物理反弹。
  5. 游戏结束

    • 玩家失败:球掉出屏幕底部;
    • 玩家胜利:所有砖块被清除。

5. 实现效果

image.png

image.png


6. 总结

通过本篇文章,你已经学会了如何使用 Python + Pygame 从零构建一个基础的打砖块游戏。该示例涵盖了碰撞检测游戏循环对象管理等常见2D游戏开发中的核心逻辑。你可以在此基础上自由发挥,加入更多道具、特效和关卡,从而打造一个更完整、更丰富的打砖块游戏。


http://www.kler.cn/a/526961.html

相关文章:

  • 计算机网络之计算机网络的分类
  • AI编程:如何编写提示词
  • chrome源码剖析—进程通信
  • 前端axios拦截器
  • Golang笔记——常用库context和runtime
  • 最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
  • 二.java开发项目 常用hutool aop mybatisplue依赖2.
  • 分布式架构中的事务管理:需要了解的常见解决方案
  • ai翻唱入门
  • priority_queue的创建_结构体类型(重载小于运算符)c++
  • 计算机网络之计算机网络协议、接口、服务等概念
  • 【MyDB】4-VersionManager 之 2-事务的隔离级别
  • pytorch实现半监督学习
  • CSS入门知识
  • VUE之组件通信(一)
  • win11本地部署 DeepSeek-R1 大模型!免费开源,媲美OpenAI-o1能力,断网也能用
  • 【数据机构】_复杂度
  • 【leetcode详解】T3175(一点反思)
  • arm-linux-gnueabihf安装
  • Retrieval-Augmented Generation for Large Language Models: A Survey——(1)Overview
  • 数据库性能优化(sql优化)_SQL执行计划03_yxy
  • Chapter 3-19. Detecting Congestion in Fibre Channel Fabrics
  • VS安卓仿真器下载失败怎么办?
  • maven mysql jdk nvm node npm 环境安装
  • KNIME:开源 AI 数据科学
  • Janus-Pro 论文解读:DeepSeek 如何重塑多模态技术格局