使用Pygame制作“打砖块”游戏
1. 前言
打砖块(Breakout / Arkanoid) 是一款经典街机游戏,玩家控制一个可左右移动的挡板,接住并反弹球,击碎屏幕上方的砖块。随着砖块被击碎,不仅能获得分数,还可以体验到不断加速或复杂的反弹乐趣。 在本篇文章里,我们将使用 Python 3.x + Pygame 库,手把手实现一个简易版本的打砖块游戏,包含最核心的移动、碰撞和得分功能。
2. 开发环境与准备
- Python 3.x
- Pygame:若尚未安装,可通过命令
pip install pygame
进行安装。 - 桌面系统:Windows、macOS 或绝大多数 Linux 桌面环境都能正常使用 Pygame。
安装完成后,使用 import pygame
测试是否成功即可。
3. 游戏思路
要完成一个打砖块游戏,需要实现以下几个关键模块:
-
挡板(Paddle)
- 位于屏幕底部,可左右移动。
- 通过键盘或鼠标控制位置。
-
球(Ball)
- 从挡板上方出发,向上运动;
- 在碰到墙壁时发生反弹;
- 在碰到挡板或砖块时,需要计算反弹方向,并可能击碎砖块、加分。
-
砖块(Bricks)
- 通常在屏幕上方排列成若干行;
- 一旦被球击中,会被击碎并增加分数;
- 也可以设定一些特殊砖块,击中后会产生道具等(此处仅做简易实现)。
-
游戏结束
- 若球掉出屏幕底部则表示丢失一条命,或者直接游戏结束;
- 如果所有砖块都被击碎,则玩家胜利。
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 = 100self.height = 15self.x = (WIDTH - self.width) // 2self.y = HEIGHT - 50self.speed = 8def draw(self, surface):pygame.draw.rect(surface, BLUE, (self.x, self.y, self.width, self.height))def move_left(self):self.x -= self.speedif self.x < 0:self.x = 0def move_right(self):self.x += self.speedif self.x + self.width > WIDTH:self.x = WIDTH - self.width# ----------------------
# 球类
# ----------------------
class Ball:def __init__(self, paddle):self.radius = 8self.x = paddle.x + paddle.width // 2self.y = paddle.y - 10# 球初始速度self.speed_x = random.choice([-4, 4])self.speed_y = -4def 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_xself.y += self.speed_y# 碰撞左右墙if self.x - self.radius < 0:self.x = self.radiusself.speed_x = -self.speed_xelif self.x + self.radius > WIDTH:self.x = WIDTH - self.radiusself.speed_x = -self.speed_x# 碰撞上墙if self.y - self.radius < 0:self.y = self.radiusself.speed_y = -self.speed_y# 掉到底部 -> 游戏结束的处理可在主循环中判断# if self.y + self.radius > HEIGHT:# pass# 碰撞挡板if (self.x > paddle.x and self.x < paddle.x + paddle.widthand self.y + self.radius > paddle.yand 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.xand self.x - self.radius < brick.x + brick.widthand self.y + self.radius > brick.yand self.y - self.radius < brick.y + brick.height):bricks.remove(brick)self.speed_y = -self.speed_y # 简化反弹,只改变垂直方向return 10 # 得分10return 0# ----------------------
# 砖块类
# ----------------------
class Brick:def __init__(self, x, y, width, height, color=GREEN):self.x = xself.y = yself.width = widthself.height = heightself.color = colordef 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) // colsbrick_height = 20x_offset = 20y_offset = 40for row in range(rows):for col in range(cols):x = x_offset + col * brick_widthy = y_offset + row * brick_heightcolor = 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 = 0running = Truewhile 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 = Falseif 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()
核心逻辑解读
-
Paddle(挡板)
- 只需实现水平移动;
- 在超出屏幕边界时,强制回到合法范围内。
-
Ball(球)
- 通过
self.x
,self.y
表示球心位置,self.speed_x
,self.speed_y
表示当前水平和垂直速度; - 每帧更新时,先加上速度;遇到左右墙、上墙时反转速度;遇到底部则表示掉落。
- 在与挡板或砖块相交时,需要根据碰撞方向做出相应反弹。
- 通过
-
Brick(砖块)
- 仅保存坐标、宽高、颜色;
- 被击中后从列表中移除。
-
碰撞检测
- 简化实现:只要球的圆心与砖块矩形区域重叠即可判断为碰撞;
- 在真实游戏中,可以做更精确的检测(圆与矩形边的距离、角度等)或更细致的物理反弹。
-
游戏结束
- 玩家失败:球掉出屏幕底部;
- 玩家胜利:所有砖块被清除。
5. 实现效果
6. 总结
通过本篇文章,你已经学会了如何使用 Python + Pygame 从零构建一个基础的打砖块游戏。该示例涵盖了碰撞检测、游戏循环、对象管理等常见2D游戏开发中的核心逻辑。你可以在此基础上自由发挥,加入更多道具、特效和关卡,从而打造一个更完整、更丰富的打砖块游戏。
相关文章:

使用Pygame制作“打砖块”游戏
1. 前言 打砖块(Breakout / Arkanoid) 是一款经典街机游戏,玩家控制一个可左右移动的挡板,接住并反弹球,击碎屏幕上方的砖块。随着砖块被击碎,不仅能获得分数,还可以体验到不断加速或复杂的反弹…...

【完整版】DeepSeek-R1大模型学习笔记(架构、训练、Infra)
文章目录 0 DeepSeek系列总览1 模型架构设计基本参数专家混合模型(MoE)[DeepSeek-V2提出, DeepSeek-V3改良]多头潜在注意力(MLA)[DeepSeek-V2提出]多token预测(MTP)[DeepSeek-V3提出] 2 DeepSeek-R1-Zero及…...
深入解析:如何利用 Python 爬虫获取商品 SKU 详细信息
在电商领域,SKU(Stock Keeping Unit,库存单位)详细信息是电商运营的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息,还直接影响到库存管理、价格策略和市场分析等多个方面。本文将详细介绍如何利用 Pyth…...
【3】高并发导出场景下,服务器性能瓶颈优化方案-文件压缩
使用EasyExcel导出并压缩文件是一种高效且常见的解决方案,尤其适用于需要处理大量数据的场景。 1. 导出多个Excel文件并压缩成ZIP文件的基本流程 (1)数据准备:从数据库或其他数据源获取需要导出的数据,并将其存储在Ja…...

FPGA|生成jic文件固化程序到flash
1、单击file-》convert programming files 2、flie type中选中jic文件,configuration decive里根据自己的硬件选择,单击flash loader选择右边的add device选项 3、选择自己的硬件,单击ok 4、选中sof选项,单机右侧的add file 5、选…...

【ArcGIS_Python】使用arcpy脚本将shape数据转换为三维白膜数据
说明: 该专栏之前的文章中python脚本使用的是ArcMap10.6自带的arcpy(好几年前的文章),从本篇开始使用的是ArcGIS Pro 3.3.2版本自带的arcpy,需要注意不同版本对应的arcpy函数是存在差异的 数据准备:准备一…...

用Python获取股票数据并实现未来收盘价的预测
获取数据 先用下面这段代码获取上证指数的历史数据,得到的csv文件数据,为后面训练模型用的 import akshare as ak import pandas as pd# 获取上证指数历史数据 df ak.stock_zh_index_daily(symbol"sh000001")# 将数据保存到本地CSV文件 df.…...

Rust 所有权特性详解
Rust 所有权特性详解 Rust 的所有权系统是其内存安全的核心机制之一。通过所有权规则,Rust 在编译时避免了常见的内存错误(如空指针、数据竞争等)。本文将从堆内存与栈内存、所有权规则、变量作用域、String 类型、内存分配、所有权移动、Cl…...
Gateway路由匹配规则详解
在微服务架构中,Gateway作为请求的入口,扮演着至关重要的角色。它不仅负责路由转发,还具备安全、监控、限流等多种功能。其中,路由匹配规则是Gateway的核心功能之一,它决定了请求如何被正确地转发到目标服务。本文将详…...
项目实操:windows批处理拉取git库和处理目录、文件
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
前端开发知识梳理 - HTMLCSS
1. 盒模型 由内容区(content)、内边距(padding)、边框(border)和外边距(margin)组成。 (1)标准盒模型(box-sizing默认值, content-boxÿ…...
nginx中的proxy_set_header参数详解
在使用 Nginx 作为反向代理服务器时,proxy_set_header 指令扮演着至关重要的角色。它允许我们自定义请求头信息,将客户端请求传递给上游服务器时,添加或修改特定的信息,从而实现更灵活的代理功能。本文将深入探讨 proxy_set_heade…...
MapReduce是什么?
MapReduce 是一种编程模型,最初由 Google 提出,旨在处理大规模数据集。它是分布式计算的一个重要概念,通常用于处理海量数据并进行并行计算。MapReduce的基本思想是将计算任务分解为两个阶段:Map 阶段和 Reduce 阶段。 Map 阶段&a…...

Text2Sql:开启自然语言与数据库交互新时代(3030)
一、Text2Sql 简介 在当今数字化时代,数据处理和分析的需求日益增长。对于众多非技术专业人员而言,数据库操作的复杂性常常成为他们获取所需信息的障碍。而 Text2Sql 技术的出现,为这一问题提供了有效的解决方案。 Text2Sql,即文…...

《图解设计模式》笔记(五)一致性
十一、Composite模式:容器与内容的一致性 像文件夹与文件一样,文件夹中可以放子文件夹与文件,再比如容器中可以放更小的容器和具体内容。 Composite模式:使容器与内容具有一致性,创造出递归结构。 Composite&#x…...

华为支付-免密支付接入免密代扣说明
免密代扣包括支付并签约以及签约代扣场景。 开发者接入免密支付前需先申请开通签约代扣产品(即申请配置免密代扣模板及协议模板ID)。 华为支付以模板维度管理每一个代扣扣费服务,主要组成要素如下: 接入免密支付需注意&#x…...
React组件中的列表渲染与分隔符处理技巧
React组件中的列表渲染与分隔符处理技巧 摘要问题背景解决方案分析方案一:数组拼接法方案二:Fragment组件方案三:动态生成key 关键技术点1. key的使用原则2. Fragment组件3. 性能优化 实战演练挑战1:动态分隔符样式挑战2ÿ…...

【Pytorch和Keras】使用transformer库进行图像分类
目录 一、环境准备二、基于Pytorch的预训练模型1、准备数据集2、加载预训练模型3、 使用pytorch进行模型构建 三、基于keras的预训练模型四、模型测试五、参考 现在大多数的模型都会上传到huggface平台进行统一的管理,transformer库能关联到huggface中对应的模型&am…...
快速了解 c++ 异常处理 基础知识
相关代码概览: #include<stdexcept>std::runtime_errorcatch (const std::runtime_error& e) e.what() 相信大家一定见过这些代码,那么这些代码具体什么意思呢?我们一起来看一下 知识精讲: 异常处理是C中非常重要…...

deepseek API 调用-python
【1】创建 API keys 【2】安装openai SDK pip3 install openai 【3】代码: https://download.csdn.net/download/notfindjob/90343352...
若依添加添加监听容器配置(删除键,键过期)
1、配置Redis的键触发事件 # 基础配置 bind 0.0.0.0 # 允许所有IP连接 protected-mode no # 关闭保护模式(生产环境建议结合密码使用) port 6379 # 默认端口 daemonize no …...

maven微服务${revision}依赖打包无法识别
1、场景描述 我现在又一个微服务项目,父pom的版本,使用<properties>定义好,如下所示: <name>ypsx-finance-center</name> <artifactId>ypsx-finance</artifactId> <packaging>pom</pack…...
【前端】常用组件的CSS
1. button的样式修改 每个环节有五个不同的状态:link,hover,active,focus和visited. Link是正常的外观,hover当你鼠标悬停时,active是单击它时的状态,focus跟随活动状态,visited是你在最近点击的链接未聚焦时结束的状态。 纯CSS 以下为例子,按下后从浅紫到深紫。注…...
在WPF项目中集成Python:Python.NET深度实战指南
随着Python在数据分析、机器学习、自动化等领域的广泛应用,越来越多的.NET开发者希望在WPF桌面应用中调用Python代码,实现两者优势互补。Python.NET(pythonnet)作为连接.NET与Python的桥梁,提供了强大的跨语言调用能力…...

NLP学习路线图(二十七):Transformer编码器/解码器
一、Transformer概览:抛弃循环,拥抱注意力 传统RNN及其变体(如LSTM、GRU)处理序列数据时存在顺序依赖的瓶颈:必须逐个处理序列元素,难以并行计算,且对长程依赖建模能力较弱。Transformer的革命…...
Gin框架实战指南:从入门到进阶
Gin框架实战指南:从入门到进阶 在当今的后端开发领域,Gin框架以其高性能、简洁易用的特点,赢得了众多Go语言开发者的青睐。本文将带你深入探索Gin框架的方方面面,从基础的安装与使用,到响应处理、请求参数解析、中间件…...

React 第五十二节 Router中 useResolvedPath使用详解和注意事项示例
前言 useResolvedPath 是 React Router v6 提供的一个实用钩子,用于解析给定路径为完整路径对象。 它根据当前路由上下文解析相对路径,生成包含 pathname、search 和 hash 的完整路径对象。 一、useResolvedPath 核心用途 路径解析:将相对…...

vue+cesium示例:地形开挖(附源码下载)
基于cesium和vue绘制多边形实现地形开挖效果,适合学习Cesium与前端框架结合开发3D可视化项目。 demo源码运行环境以及配置 运行环境:依赖Node安装环境,demo本地Node版本:推荐v18。 运行工具:vscode或者其他工具。 配置方式&#x…...

DAY45 可视化
DAY 45 Tensorborad 之前的内容中,我们在神经网络训练中,为了帮助自己理解,借用了很多的组件,比如训练进度条、可视化的loss下降曲线、权重分布图,运行结束后还可以查看单张图的推理效果。 如果现在有一个交互工具可…...
RetroMAE 预训练任务
RetroMAE 预训练任务的具体步骤,围绕 编码(Encoding)、解码(Decoding)、增强解码(Enhanced decoding) 三个核心阶段展开,以下结合图中流程拆解: 一、阶段 A:…...