文章目录
Python用Pygame手把手教你编写贪吃蛇游戏
贪吃蛇是经典的小游戏,通过方向键控制蛇移动,吃到食物后蛇身变长,撞到自己则游戏结束。今天我们用Pygame库从零开始实现这个游戏,全程代码逐行讲解,新手也能轻松掌握。

一、准备工作
首先确保安装了Pygame库,若未安装,在命令行执行:
pip install pygame
二、完整代码与逐行讲解
下面是完整的贪吃蛇游戏代码,我们会按功能模块拆分讲解:
import pygame
import sys
import random
功能:导入必要的库
pygame:用于游戏开发的核心库(处理图形、声音、输入等)sys:用于处理程序退出random:用于生成随机位置(食物的位置)
# 1. 初始化
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("贪吃蛇")
clock = pygame.time.Clock()
font = pygame.font.SysFont("SimHei", 30)
功能:游戏初始化设置
pygame.init():初始化Pygame所有模块(必须调用,否则Pygame无法工作)pygame.display.set_mode((600, 600)):创建一个600x600像素的游戏窗口,返回窗口对象screenpygame.display.set_caption("贪吃蛇"):设置窗口标题为“贪吃蛇”clock = pygame.time.Clock():创建时钟对象,用于控制游戏帧率(蛇的移动速度)font = pygame.font.SysFont("SimHei", 30):创建字体对象(支持中文“SimHei”,大小30),用于显示分数和游戏结束文字
# 2. 游戏常量
GRID_SIZE = 30 # 每个网格的像素大小
GRID_WIDTH = 600 // GRID_SIZE # 网格的列数(600/30=20列)
GRID_HEIGHT = 600 // GRID_SIZE # 网格的行数(600/30=20行)
功能:定义游戏核心常量
- 把窗口划分为20x20的网格(每个网格30像素),蛇和食物都在网格上移动,方便定位和碰撞检测
# 3. 蛇类
class Snake:
def __init__(self):
self.body = [(10, 10)] # 初始位置:蛇身由多个坐标组成,初始只有一个头部在(10,10)网格
self.direction = (1, 0) # 初始方向:(x偏移量,y偏移量),(1,0)表示向右移动
self.grow = False # 是否需要成长:吃到食物后设为True,蛇身增加一节
def update(self):
# 计算新头部位置
head_x, head_y = self.body[0] # 获取当前头部坐标
dx, dy = self.direction # 获取当前移动方向的偏移量
# 新头部坐标 = 当前头部 + 偏移量,用取模确保蛇能穿过边界(比如从右边界出去,从左边界进来)
new_head = ((head_x + dx) % GRID_WIDTH, (head_y + dy) % GRID_HEIGHT)
# 碰撞检测:如果新头部撞到自己的身体,返回False(游戏结束)
if new_head in self.body:
return False
# 更新蛇身:新头部插入到蛇身最前面
self.body.insert(0, new_head)
# 如果不需要成长,就删除尾部(保持长度不变);如果需要成长(吃到食物),则保留尾部(长度+1)
if not self.grow:
self.body.pop()
else:
self.grow = False # 重置成长标志
return True # 移动成功,游戏继续
def draw(self, screen):
# 绘制蛇的每个身体部分
for segment in self.body:
x, y = segment # 网格坐标
# 转换为像素坐标:网格x*网格大小 = 像素x,网格y*网格大小 = 像素y
# 矩形大小为GRID_SIZE-1(留1像素间隙,让蛇身分段更明显)
rect = pygame.Rect(x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1)
pygame.draw.rect(screen, (0, 255, 0), rect) # 绘制绿色矩形(蛇身)
功能:封装蛇的属性和行为
__init__:初始化蛇的初始位置、方向和成长状态update:核心方法,负责蛇的移动逻辑(计算新头部、碰撞检测、更新身体长度)draw:负责在屏幕上绘制蛇(每个身体部分都是绿色矩形)
# 4. 食物类
class Food:
def __init__(self, snake_body):
# 初始化时生成一个不在蛇身上的随机位置
self.position = self.random_position(snake_body)
def random_position(self, snake_body):
# 循环生成随机位置,直到位置不在蛇身上(避免食物出现在蛇身上)
while True:
x = random.randint(0, GRID_WIDTH - 1) # 随机列(0到19)
y = random.randint(0, GRID_HEIGHT - 1) # 随机行(0到19)
if (x, y) not in snake_body:
return (x, y) # 返回有效的食物位置
def draw(self, screen):
# 绘制食物(红色矩形)
x, y = self.position
rect = pygame.Rect(x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1)
pygame.draw.rect(screen, (255, 0, 0), rect) # 绘制红色矩形(食物)
功能:封装食物的属性和行为
__init__:初始化食物位置(确保不在蛇身上)random_position:生成随机位置的工具方法,避免食物与蛇重叠draw:在屏幕上绘制食物(红色矩形)
# 5. 主游戏逻辑
def main():
snake = Snake() # 创建蛇对象
food = Food(snake.body) # 创建食物对象(初始位置避开蛇身)
score = 0 # 分数初始化为0
game_over = False # 游戏是否结束的标志
while True: # 游戏主循环(无限循环,直到退出)
# 事件处理:监听键盘/鼠标输入
for event in pygame.event.get():
if event.type == pygame.QUIT: # 点击窗口关闭按钮
pygame.quit() # 退出Pygame
sys.exit() # 退出程序
# 游戏未结束时,处理方向键控制
if event.type == pygame.KEYDOWN and not game_over:
# 按上键且当前方向不是向下(避免180度转向撞到自己)
if event.key == pygame.K_UP and snake.direction != (0, 1):
snake.direction = (0, -1) # 方向改为向上(y轴-1)
# 按下键且当前方向不是向上
elif event.key == pygame.K_DOWN and snake.direction != (0, -1):
snake.direction = (0, 1) # 方向改为向下(y轴+1)
# 按左键且当前方向不是向右
elif event.key == pygame.K_LEFT and snake.direction != (1, 0):
snake.direction = (-1, 0) # 方向改为向左(x轴-1)
# 按右键且当前方向不是向左
elif event.key == pygame.K_RIGHT and snake.direction != (-1, 0):
snake.direction = (1, 0) # 方向改为向右(x轴+1)
# 游戏未结束时,更新游戏状态
if not game_over:
# 更新蛇的位置,如果返回False(撞到自己),则游戏结束
if not snake.update():
game_over = True
# 检测是否吃到食物(蛇头坐标 == 食物坐标)
if snake.body[0] == food.position:
score += 10 # 分数+10
snake.grow = True # 蛇需要成长
food = Food(snake.body) # 重新生成食物
# 绘制游戏元素
screen.fill((0, 0, 0)) # 填充黑色背景(每次绘制前清空屏幕)
snake.draw(screen) # 绘制蛇
food.draw(screen) # 绘制食物
# 显示分数
score_text = font.render(f"分数: {score}", True, (255, 255, 255)) # 生成白色文字
screen.blit(score_text, (10, 10)) # 把文字绘制到屏幕(10,10)位置
# 游戏结束时显示提示
if game_over:
over_text = font.render("游戏结束!按ESC退出", True, (255, 0, 0)) # 生成红色文字
screen.blit(over_text, (200, 300)) # 文字绘制到屏幕中间
# 按ESC键退出游戏
if pygame.key.get_pressed()[pygame.K_ESCAPE]:
pygame.quit()
sys.exit()
pygame.display.flip() # 刷新屏幕(让绘制的内容显示出来)
clock.tick(10) # 控制帧率为10(每秒最多10帧,即蛇每秒移动10格)
if __name__ == "__main__":
main() # 启动游戏
功能:主游戏逻辑控制
- 初始化游戏对象(蛇、食物、分数)
- 主循环:持续处理输入、更新游戏状态、绘制画面
- 事件处理:监听窗口关闭和方向键输入,控制蛇的移动方向(避免反向移动)
- 状态更新:蛇的移动、碰撞检测、食物刷新、分数计算
- 画面绘制:背景、蛇、食物、分数和游戏结束提示
- 帧率控制:通过
clock.tick(10)限制蛇的移动速度(数值越大速度越快)
三、游戏操作说明
- 运行程序后,会显示一个600x600的窗口,绿色的蛇初始在中间位置
- 用方向键(↑↓←→)控制蛇的移动方向
- 蛇吃到红色食物后,身体变长,分数+10
- 蛇头撞到自己的身体时,游戏结束,按ESC键退出
四、拓展思路
如果想让游戏更有趣,可以尝试这些改进:
- 增加难度:随着分数提高,蛇的移动速度加快
- 增加障碍物:在地图上随机生成障碍物,撞到障碍物游戏结束
- 记录最高分:将最高分保存到文件,下次游戏时显示
- 改变外观:给蛇和食物添加图片(用
pygame.image.load加载图片)
通过这个案例,我们掌握了Pygame的基本用法:窗口创建、事件处理、图形绘制、帧率控制,以及面向对象编程(用类封装游戏元素)。试着自己修改代码,体验编程的乐趣吧!
2213

被折叠的 条评论
为什么被折叠?



