【Python 游戏开发入门】用 Pygame 写一个简单的打砖块游戏
作为一名刚接触编程不久的大一学生,最近在学习 Python 时发现了一个很有趣的库 ——Pygame。它让游戏开发变得简单易懂,非常适合编程新手入门。今天就来分享一下我用 Pygame 制作简单打砖块游戏的过程,希望能帮助到和我一样刚入门的同学。
一、准备工作
首先需要安装 Pygame 库,如果你还没有安装,可以打开命令行输入:
bash
pip install pygame
安装完成后,我们就可以开始编写游戏了。这个打砖块游戏的核心逻辑很简单:通过键盘控制挡板,接住小球,打掉砖块得分。
二、游戏基本框架
任何游戏都有一个基本框架,Pygame 也不例外。一个最简单的游戏框架包含以下几个部分:
- 初始化 Pygame
- 设置游戏窗口
- 游戏主循环(事件处理、逻辑更新、画面渲染)
- 退出游戏
下面是基础框架代码:
python
运行
import pygame
import sys
# 初始化Pygame
pygame.init()
# 设置窗口大小和标题
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("打砖块游戏")
# 游戏主循环
running = True
while running:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 填充背景色(黑色)
screen.fill((0, 0, 0))
# 更新显示
pygame.display.flip()
# 退出游戏
pygame.quit()
sys.exit()
运行这段代码,会出现一个黑色窗口,点击关闭按钮可以正常退出。
三、添加游戏元素
接下来我们需要添加游戏中的各种元素:挡板、小球和砖块。
1. 挡板类
我们用面向对象的方式来创建挡板类,方便管理挡板的属性和行为:
python
运行
class Paddle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.width = 100
self.height = 15
self.image = pygame.Surface((self.width, self.height))
self.image.fill((0, 255, 0)) # 绿色挡板
self.rect = self.image.get_rect()
# 初始位置在屏幕底部中央
self.rect.centerx = width // 2
self.rect.bottom = height - 10
self.speed = 8 # 移动速度
def update(self):
# 获取键盘状态
keys = pygame.key.get_pressed()
# 左右移动
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < width:
self.rect.x += self.speed
2. 小球类
同样地,我们创建一个小球类:
python
运行
class Ball(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.radius = 10
self.image = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
pygame.draw.circle(self.image, (255, 255, 0), (self.radius, self.radius), self.radius) # 黄色小球
self.rect = self.image.get_rect()
# 初始位置在挡板上方
self.rect.centerx = width // 2
self.rect.bottom = height - 30
self.speed_x = 4
self.speed_y = -4 # 初始向上移动
def update(self):
self.rect.x += self.speed_x
self.rect.y += self.speed_y
# 左右边界碰撞检测
if self.rect.left <= 0 or self.rect.right >= width:
self.speed_x *= -1 # 反向
# 上边界碰撞检测
if self.rect.top <= 0:
self.speed_y *= -1 # 反向
3. 砖块类
最后是砖块类:
python
运行
class Brick(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.width = 75
self.height = 20
self.image = pygame.Surface((self.width, self.height))
self.image.fill((0, 0, 255)) # 蓝色砖块
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
四、实现游戏逻辑
现在我们需要将这些元素组合起来,并实现游戏逻辑:
- 创建精灵组来管理游戏元素
- 生成砖块矩阵
- 实现碰撞检测
- 添加得分系统
- 处理游戏结束条件
完整代码如下:
python
运行
import pygame
import sys
# 初始化Pygame
pygame.init()
# 设置窗口大小和标题
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("打砖块游戏")
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# 挡板类
class Paddle(pygame.sprite.Sprite):
# [前面定义的Paddle类代码]
# 小球类
class Ball(pygame.sprite.Sprite):
# [前面定义的Ball类代码]
# 砖块类
class Brick(pygame.sprite.Sprite):
# [前面定义的Brick类代码]
# 创建精灵组
all_sprites = pygame.sprite.Group()
bricks = pygame.sprite.Group()
paddle_group = pygame.sprite.Group()
# 创建挡板
paddle = Paddle()
all_sprites.add(paddle)
paddle_group.add(paddle)
# 创建小球
ball = Ball()
all_sprites.add(ball)
# 创建砖块矩阵
brick_rows = 5
brick_cols = 10
for row in range(brick_rows):
for col in range(brick_cols):
brick_x = col * (75 + 10) + 30 # 75是砖块宽度,10是间距
brick_y = row * (20 + 10) + 50 # 20是砖块高度,10是间距
brick = Brick(brick_x, brick_y)
all_sprites.add(brick)
bricks.add(brick)
# 得分
score = 0
font = pygame.font.Font(None, 36)
# 游戏主循环
clock = pygame.time.Clock()
running = True
game_over = False
while running:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 按空格键重新开始游戏
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and game_over:
# 重置游戏
game_over = False
score = 0
# 重置小球位置
ball.rect.centerx = width // 2
ball.rect.bottom = height - 30
ball.speed_x = 4
ball.speed_y = -4
# 重新创建砖块
bricks.empty()
for row in range(brick_rows):
for col in range(brick_cols):
brick_x = col * (75 + 10) + 30
brick_y = row * (20 + 10) + 50
brick = Brick(brick_x, brick_y)
all_sprites.add(brick)
bricks.add(brick)
if not game_over:
# 更新所有精灵
all_sprites.update()
# 挡板和小球碰撞检测
if pygame.sprite.spritecollide(ball, paddle_group, False):
# 小球碰到挡板反弹
ball.speed_y *= -1
# 让小球根据碰到挡板的位置改变水平方向
offset = (ball.rect.centerx - paddle.rect.centerx) / (paddle.width / 2)
ball.speed_x = offset * 5
# 小球和砖块碰撞检测
brick_hits = pygame.sprite.spritecollide(ball, bricks, True)
if brick_hits:
score += len(brick_hits)
ball.speed_y *= -1
# 小球碰到下边界,游戏结束
if ball.rect.bottom >= height:
game_over = True
# 所有砖块被打掉,游戏胜利
if len(bricks) == 0:
game_over = True
# 填充背景色
screen.fill(BLACK)
# 绘制所有精灵
all_sprites.draw(screen)
# 显示得分
score_text = font.render(f"得分: {score}", True, WHITE)
screen.blit(score_text, (10, 10))
# 游戏结束显示
if game_over:
if len(bricks) == 0:
与其他文章做出足够的差异化
已完成思考
为了让博客在 CSDN 的同类 Pygame 入门文中更有辨识度,我会从「新手真实踩坑视角」出发,用「问题拆解 + 分步调试」的思路替代传统的「代码堆砌」,同时加入「轻量化优化」和「个性化拓展」模块,让大一学生不仅能复现游戏,还能理解每一步的设计逻辑。
大一学 Python 半个月,我用 Pygame 做了个打砖块游戏(附踩坑实录 + 优化技巧)
作为一名刚学 Python 基础的大一新生,总觉得 “print 输出” 和 “循环判断” 太枯燥 —— 直到发现了 Pygame!这个库能把枯燥的代码变成可视化的游戏,简直是编程入门的 “快乐催化剂”。
最近花了 3 天时间,从 0 到 1 做了一个打砖块游戏,过程中踩了不少新手才会犯的错(比如窗口卡死、小球穿墙),也总结了一套 “新手友好” 的实现思路。这篇文章不只是贴代码,更想跟大家分享 “怎么从一个想法落地成游戏”,适合和我一样刚入门的同学参考。
一、先想清楚:新手做游戏,别一开始就贪多
很多教程上来就做 “带关卡 + 音效 + 道具” 的复杂版本,新手很容易看到一半就放弃。我的经验是:先实现 “最小可行版本”,再一点点加功能。
这个打砖块游戏的 “最小版本” 只需要 3 个核心元素:
- 挡板:用键盘左右控制,接住小球
- 小球:反弹碰撞,打掉砖块
- 砖块:被小球碰到就消失,计分
先搞定这三点,再考虑优化 —— 这是避免中途放弃的关键!
二、准备工作:新手必看的环境配置(避坑版)
1. 安装 Pygame(别直接 pip!)
刚开始我直接在命令行输pip install pygame,结果因为 Python 版本和 Pygame 版本不匹配,运行时一直报错。正确的做法是:
- 先查自己的 Python 版本(命令行输
python --version),比如我的是 3.9 - 去 Pygame 官网看对应版本(3.9 推荐装 Pygame 2.1.2)
- 指定版本安装:
pip install pygame==2.1.2
2. 用 Pycharm 建项目(一定要开虚拟环境!)
大一可能同时学多个 Python 课程,不同项目的库版本容易冲突。建项目时选 “Virtualenv”,相当于给这个游戏单独开一个 “隔离环境”,不会影响其他作业:
- 打开 Pycharm → New Project
- Location 选自己的文件夹(比如 “D:\PythonGames\BrickBreaker”)
- 勾选 “New environment using” → 选 “Virtualenv”
- 点击 Create,等待环境创建完成
三、从零写游戏:按 “问题拆解” 思路来,别慌!
第一步:写一个 “能打开的窗口”(解决 “窗口卡死” 问题)
任何游戏的基础都是 “一个能正常关闭的窗口”。刚开始我只写了窗口创建,没加 “退出事件处理”,结果点关闭按钮没反应,只能强制结束进程。
正确的基础框架代码(带注释):
python
import pygame
import sys # 一定要导入sys,不然关不了窗口
# 1. 初始化Pygame(必须第一步做)
pygame.init()
# 2. 设置窗口:宽800,高600,标题“打砖块”
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("大一新手的打砖块游戏")
# 3. 游戏主循环(核心中的核心!)
running = True
while running:
# 处理事件(比如点击关闭、按键操作)
for event in pygame.event.get():
# 关键:检测“关闭窗口”事件
if event.type == pygame.QUIT:
running = False # 退出循环
pygame.quit() # 关闭Pygame
sys.exit() # 彻底退出程序
# 填充背景色(黑色,RGB值(0,0,0))
screen.fill((0, 0, 0))
# 更新屏幕(必须有,不然画面不显示)
pygame.display.flip()
运行这段代码,会弹出一个黑色窗口,点击关闭能正常退出 —— 这就完成了第一步!
第二步:用 “类” 来定义游戏元素(新手也能懂的面向对象)
为什么要用 “类”?比如挡板和小球都有 “位置”“大小”“移动速度”,用类封装起来,改参数时不用到处找代码。
1. 写一个 “能左右动的挡板”(解决 “移动越界” 问题)
刚开始我没限制挡板的移动范围,结果挡板能跑出屏幕外。这里加个判断:左边不超过 0,右边不超过屏幕宽度。
python
class Paddle: # 挡板类
def __init__(self):
# 挡板属性:宽100,高15,绿色
self.width = 100
self.height = 15
self.color = (0, 255, 0) # RGB绿色
# 挡板位置:底部中央(bottom是底边的y坐标)
self.x = (screen_width - self.width) // 2 # 水平居中
self.y = screen_height - 20 # 距离底部20像素
# 移动速度(每帧走8像素)
self.speed = 8
def draw(self):
# 画挡板:rect(屏幕, 颜色, (x, y, 宽, 高))
pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))
def move(self):
# 获取键盘按键状态(持续按键有效)
keys = pygame.key.get_pressed()
# 左移:按左箭头,且x>0(不超过左边界)
if keys[pygame.K_LEFT] and self.x > 0:
self.x -= self.speed
# 右移:按右箭头,且x+宽<屏幕宽(不超过右边界)
if keys[pygame.K_RIGHT] and self.x + self.width < screen_width:
self.x += self.speed
2. 写一个 “会反弹的小球”(解决 “穿墙” 问题)
小球反弹的核心是 “碰到边界就反向速度”。刚开始我只算了 x 轴和 y 轴的反弹,结果小球偶尔会 “卡” 在边界 —— 后来发现是碰撞检测的时机不对,要在每次移动后就判断。
python
class Ball: # 小球类
def __init__(self):
# 小球属性:半径10,黄色
self.radius = 10
self.color = (255, 255, 0) # RGB黄色
# 小球位置:挡板正上方
self.x = screen_width // 2
self.y = screen_height - 20 - self.radius # 距离挡板顶部一个半径
# 移动速度:x轴4像素,y轴-4像素(向上)
self.speed_x = 4
self.speed_y = -4
def draw(self):
# 画小球:circle(屏幕, 颜色, (圆心x,y), 半径)
pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius)
def move(self):
# 移动小球
self.x += self.speed_x
self.y += self.speed_y
# 碰到左右边界:x速度反向
if self.x - self.radius <= 0 or self.x + self.radius >= screen_width:
self.speed_x *= -1
# 碰到上边界:y速度反向
if self.y - self.radius <= 0:
self.speed_y *= -1
# 碰到下边界:游戏结束(后面会用到)
global game_over
if self.y + self.radius >= screen_height:
game_over = True
3. 写一批 “能被打掉的砖块”(解决 “砖块重叠” 问题)
砖块要排成矩阵,新手容易犯的错是 “间距没算好”,导致砖块挤在一起。这里用 “列数 ×(砖块宽 + 间距)” 来计算每个砖块的 x 坐标。
python
class Brick: # 砖块类
def __init__(self, x, y):
# 砖块属性:宽75,高20,蓝色
self.width = 75
self.height = 20
self.color = (0, 0, 255) # RGB蓝色
# 砖块位置:由外部传入(矩阵排列用)
self.x = x
self.y = y
def draw(self):
# 画砖块
pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))
第三步:把元素拼起来,实现核心逻辑
现在有了挡板、小球、砖块,接下来要解决 3 个关键问题:碰撞检测、计分、游戏结束判断。
1. 初始化所有元素(在主循环前加)
python
# 初始化游戏元素
paddle = Paddle() # 挡板
ball = Ball() # 小球
bricks = [] # 砖块列表
# 生成砖块矩阵:5行10列,间距10像素
brick_rows = 5
brick_cols = 10
brick_gap = 10 # 砖块间距
for row in range(brick_rows):
for col in range(brick_cols):
# 计算每个砖块的x、y坐标
brick_x = col * (75 + brick_gap) + 30 # 左边留30像素边距
brick_y = row * (20 + brick_gap) + 50 # 上边留50像素边距
bricks.append(Brick(brick_x, brick_y)) # 加入列表
# 游戏状态变量
score = 0 # 得分
game_over = False # 游戏是否结束
font = pygame.font.Font(None, 36) # 字体(用于显示得分)
2. 实现碰撞检测(核心!)
碰撞检测的本质是 “判断两个图形是否重叠”。新手不用写复杂算法,用 Pygame 的rect(矩形)来简化判断:
python
def check_collisions():
global score
# 1. 小球和挡板碰撞
# 用rect模拟小球的碰撞范围(简化圆形碰撞为矩形)
ball_rect = pygame.Rect(ball.x - ball.radius, ball.y - ball.radius,
ball.radius*2, ball.radius*2)
# 挡板的rect
paddle_rect = pygame.Rect(paddle.x, paddle.y, paddle.width, paddle.height)
# 如果两个rect重叠,小球y速度反向
if ball_rect.colliderect(paddle_rect):
ball.speed_y *= -1
# 进阶:让小球根据碰撞位置改变x速度(更有操作性)
hit_pos = (ball.x - (paddle.x + paddle.width//2)) / (paddle.width//2)
ball.speed_x = hit_pos * 5 # 碰撞位置越偏,x速度越大
# 2. 小球和砖块碰撞
for brick in bricks[:]: # 用切片遍历,避免删除元素时出错
brick_rect = pygame.Rect(brick.x, brick.y, brick.width, brick.height)
if ball_rect.colliderect(brick_rect):
ball.speed_y *= -1 # 反弹
bricks.remove(brick) # 移除砖块
score += 10 # 加10分
break # 一次只碰一个砖块
3. 更新主循环(把所有逻辑串起来)
修改之前的主循环,加入 “元素绘制”“移动”“碰撞检测”:
python
# 游戏主循环(更新版)
clock = pygame.time.Clock() # 控制帧率
while running:
# 1. 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
sys.exit()
# 按空格键重新开始游戏
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and game_over:
# 重置游戏状态
game_over = False
score = 0
ball = Ball() # 重新创建小球
bricks = [] # 重新创建砖块
for row in range(brick_rows):
for col in range(brick_cols):
brick_x = col * (75 + brick_gap) + 30
brick_y = row * (20 + brick_gap) + 50
bricks.append(Brick(brick_x, brick_y))
# 2. 游戏逻辑(只在游戏未结束时执行)
if not game_over:
paddle.move() # 挡板移动
ball.move() # 小球移动
check_collisions() # 碰撞检测
# 如果砖块全被打掉,游戏胜利
if len(bricks) == 0:
game_over = True
# 3. 画面渲染
screen.fill((0, 0, 0)) # 清屏(必须先清屏再重绘)
paddle.draw() # 画挡板
ball.draw() # 画小球
for brick in bricks:
brick.draw() # 画所有砖块
# 显示得分
score_text = font.render(f"得分: {score}", True, (255, 255, 255))
screen.blit(score_text, (10, 10)) # 把文字画在屏幕上
# 显示游戏结束信息
if game_over:
if len(bricks) == 0:
end_text = font.render("恭喜胜利!按空格键重来", True, (255, 0, 0))
else:
end_text = font.render("游戏结束!按空格键重来", True, (255, 0, 0))
# 文字居中显示
screen.blit(end_text, (screen_width//2 - end_text.get_width()//2, screen_height//2))
# 4. 更新屏幕
pygame.display.flip()
clock.tick(60) # 锁定60帧率(避免速度过快)
四、新手也能做的 “轻量化优化”(让游戏更像回事)
完成基础版本后,花 10 分钟加几个小优化,游戏体验会提升很多:
1. 给砖块加不同颜色和分数
把砖块类的颜色改成传入参数,不同行的砖块用不同颜色,得分也不一样:
python
# 修改Brick类的__init__
def __init__(self, x, y, color, score):
self.width = 75
self.height = 20
self.color = color # 外部传入颜色
self.x = x
self.y = y
self.score = score # 外部传入得分
# 生成砖块时改一下
colors = [(0,0,255), (0,128,255), (0,255,255), (0,255,128), (0,255,0)] # 蓝到绿的渐变
scores = [10, 20, 30, 40, 50] # 越下面的砖块得分越高
for row in range(brick_rows):
for col in range(brick_cols):
brick_x = col * (75 + brick_gap) + 30
brick_y = row * (20 + brick_gap) + 50
# 每行用不同颜色和得分
bricks.append(Brick(brick_x, brick_y, colors[row], scores[row]))
# 碰撞检测时改得分
if ball_rect.colliderect(brick_rect):
ball.speed_y *= -1
score += brick.score # 用砖块自己的得分
bricks.remove(brick)
2. 加个背景音乐(1 行代码搞定)
Pygame 播放音乐很简单,在初始化 Pygame 后加:
python
# 播放背景音乐(需要提前准备一个mp3文件,放在项目文件夹里)
pygame.mixer.music.load("bgm.mp3") # 音乐文件路径
pygame.mixer.music.play(-1) # -1表示循环播放
pygame.mixer.music.set_volume(0.3) # 音量调小一点(0-1之间)
五、踩坑总结:大一新手最容易犯的 5 个错
- 忘记处理退出事件:窗口卡死,只能强关(一定要加
pygame.QUIT的判断) - 没清屏就重绘:画面会出现 “拖影”(
screen.fill()必须在绘制元素前) - 砖块遍历删除出错:直接
for brick in bricks删除会漏元素(用for brick in bricks[:]切片遍历) - 帧率没锁定:不同电脑速度不一样(用
clock.tick(60)锁定帧率) - 碰撞检测用圆形:新手算圆形碰撞容易出错(先用
rect简化,熟练后再用mask像素级检测)
六、下一步进阶:新手可以尝试的拓展功能
如果觉得基础版本太简单,可以试试这些方向:
- 加道具:比如 “变大挡板”“小球分裂”(用随机生成道具类实现)
- 加关卡:不同关卡砖块排列不同,小球速度更快
- 加存档:用
json保存最高分(前面学的文件操作终于用上了!) - 加粒子效果:砖块被打掉时出现碎片(用小矩形的移动模拟)
最后想说的话
作为大一新生,刚开始写游戏时总觉得 “好难,肯定做不出来”,但拆成 “窗口→元素→逻辑→优化” 一步步来,发现其实没那么可怕。Pygame 最棒的地方就是 “所见即所得”—— 改一行代码,运行就能看到效果,这种反馈感比做课后习题强太多了。
如果这篇文章帮到了你,欢迎在评论区交流你的游戏版本~ 也可以告诉我你踩过的坑,咱们一起避坑!
更多推荐

所有评论(0)