使用Pygame制作“贪吃蛇”游戏
创作时间:
作者:
@小白创作中心
使用Pygame制作“贪吃蛇”游戏
引用
CSDN
1.
https://blog.csdn.net/weixin_41793160/article/details/145405247
贪吃蛇是一款经典的休闲小游戏:玩家通过操控一条会不断变长的“蛇”在屏幕中移动,去吃随机出现的食物,同时要避免撞到墙壁或自己身体的其他部分。由于其逻辑相对简单,但可玩性和扩展性都不错,非常适合作为新手练习游戏编程的项目。在本篇博客中,我们将使用Python语言 +Pygame库来从零实现一款贪吃蛇。
开发环境准备
- Python 3.x
- Pygame库:如果尚未安装,请在命令行执行:
pip install pygame
- 图形界面环境:在常见的桌面系统(Windows、macOS、Linux)上都可以正常运行 Pygame 程序。
游戏实现思路
要实现一个简易的贪吃蛇,主要需要以下几个要点:
- 游戏界面
- 一般的做法是将屏幕拆分成网格(如 20×20 的方格),蛇和食物都在这些方格坐标上移动。
- 每一个方格的大小可定义为 20×20 或更适合你需求的像素。
- 蛇的运动每次走一格,方向由玩家通过箭头键或 WASD 控制。
- 蛇的表示
- 通常用一个列表来储存蛇身每个“方块”的坐标(从头到尾依次存放)。
- 当蛇移动时,需要在头部插入一个新的坐标(根据方向计算),同时移除最后一个坐标(蛇尾)来保持“长度”不变;只有当蛇吃到食物时,才不移除尾部,从而实现“变长”。
- 食物的产生
- 在网格上随机产生一个坐标点,作为食物。
- 当蛇头和食物坐标重合时,表示蛇吃到了食物,此时增加蛇的长度并在其他空格处随机生成新的食物。
- 边界与身体碰撞检测
- 边界检测:如果蛇头超出屏幕范围,则表示撞墙,游戏结束。
- 身体碰撞检测:如果蛇头的坐标跟身体某个方块相同,表示咬到自己,游戏结束。
- 游戏循环
- 使用 Pygame 的事件与时钟,循环更新游戏状态:接收玩家按键,移动蛇头,检测碰撞,更新得分等。
完整示例代码
将以下代码保存为 snake_game.py
并运行,即可体验一个最基本版本的贪吃蛇。你可以根据自己的需求对其中的参数或逻辑进行修改和完善。
import pygame
import random
import sys
# 初始化 Pygame
pygame.init()
# ---------------------
# 全局配置
# ---------------------
BLOCK_SIZE = 20 # 蛇和食物的大小(方块尺寸)
GRID_WIDTH = 30 # 水平方向方块数
GRID_HEIGHT = 20 # 垂直方向方块数
SCREEN_WIDTH = GRID_WIDTH * BLOCK_SIZE
SCREEN_HEIGHT = GRID_HEIGHT * BLOCK_SIZE
FPS = 10 # 游戏刷新率(蛇移动速度)
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 200, 0)
GRAY = (50, 50, 50)
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("贪吃蛇 - Pygame")
# 字体
font = pygame.font.SysFont("arial", 24)
# ---------------------
# 功能函数
# ---------------------
def draw_text(text, color, x, y):
"""在屏幕指定位置绘制文字"""
surface = font.render(text, True, color)
screen.blit(surface, (x, y))
def draw_block(color, x, y):
"""在(x, y)绘制一个BLOCK_SIZE大小的方块"""
rect = pygame.Rect(x, y, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(screen, color, rect)
# ---------------------
# 蛇类
# ---------------------
class Snake:
def __init__(self):
# 蛇初始位置(列表: 记录蛇身每个方块的坐标)
# 例如[(x1, y1), (x2, y2), ...] 从头到尾
self.body = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
self.direction = 'UP' # 初始方向:上
self.grow = False # 标识是否需要增长身体
def move(self):
# 计算新头部位置
head_x, head_y = self.body[0]
if self.direction == 'UP':
head_y -= 1
elif self.direction == 'DOWN':
head_y += 1
elif self.direction == 'LEFT':
head_x -= 1
elif self.direction == 'RIGHT':
head_x += 1
new_head = (head_x, head_y)
self.body.insert(0, new_head) # 头部插入到列表最前
# 如果不需要生长,则移除尾部
if not self.grow:
self.body.pop()
else:
self.grow = False # 本次已经完成增长
def change_direction(self, new_dir):
"""
根据玩家按键改变蛇的方向,
但需要防止蛇直接掉头(如当前在往左跑,不可立即改成往右)
"""
opposite = {'UP': 'DOWN', 'DOWN': 'UP', 'LEFT': 'RIGHT', 'RIGHT': 'LEFT'}
if new_dir != opposite[self.direction]:
self.direction = new_dir
def check_collision(self):
"""
检测是否撞墙或撞自己:
- 撞墙: 头部超出网格范围
- 撞自己: 头部坐标出现在身体其他部分
"""
head_x, head_y = self.body[0]
# 撞墙
if head_x < 0 or head_x >= GRID_WIDTH or head_y < 0 or head_y >= GRID_HEIGHT:
return True
# 撞自己
if self.body[0] in self.body[1:]:
return True
return False
def draw(self):
"""绘制蛇"""
for block in self.body:
x_coord = block[0] * BLOCK_SIZE
y_coord = block[1] * BLOCK_SIZE
draw_block(GREEN, x_coord, y_coord)
# ---------------------
# 食物类
# ---------------------
class Food:
def __init__(self):
self.position = self.random_pos()
def random_pos(self):
"""随机生成食物坐标(网格中)"""
return (random.randint(0, GRID_WIDTH - 1),
random.randint(0, GRID_HEIGHT - 1))
def draw(self):
"""绘制食物"""
x_coord = self.position[0] * BLOCK_SIZE
y_coord = self.position[1] * BLOCK_SIZE
draw_block(RED, x_coord, y_coord)
# ---------------------
# 游戏主函数
# ---------------------
def main():
clock = pygame.time.Clock()
snake = Snake()
food = Food()
score = 0
running = True
while running:
clock.tick(FPS) # 控制游戏帧率(蛇移动速度)
# 1) 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
snake.change_direction('UP')
elif event.key == pygame.K_DOWN:
snake.change_direction('DOWN')
elif event.key == pygame.K_LEFT:
snake.change_direction('LEFT')
elif event.key == pygame.K_RIGHT:
snake.change_direction('RIGHT')
# 2) 更新游戏状态 (蛇移动, 检测碰撞, 食物处理)
snake.move()
# 如果蛇头与食物位置相同 => 吃到食物
if snake.body[0] == food.position:
score += 1
snake.grow = True
food.position = food.random_pos()
# 检测蛇是否撞墙或撞自己
if snake.check_collision():
running = False
# 3) 绘制游戏界面
screen.fill(BLACK) # 清屏(背景黑色)
snake.draw()
food.draw()
draw_text(f"Score: {score}", WHITE, 10, 10)
pygame.display.flip()
# 如果跳出主循环,说明游戏结束
game_over(screen, score)
def game_over(surface, score):
"""
游戏结束界面,可在此添加重来或退出选项
"""
surface.fill(GRAY)
draw_text("Game Over!", WHITE, SCREEN_WIDTH // 2 - 60, SCREEN_HEIGHT // 2 - 30)
draw_text(f"Your Score: {score}", WHITE, SCREEN_WIDTH // 2 - 70, SCREEN_HEIGHT // 2 + 10)
pygame.display.flip()
# 等待若干秒后退出
pygame.time.wait(3000)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
核心逻辑解析
- Snake 类
- 用一个列表
body
存储从头到尾的网格坐标。 move()
函数在前面插入新的头部坐标,如不需要增长则移除尾部。check_collision()
判断是否超出网格边界或头部与身体其他部分重合。
- Food 类
- 只需保存一个
position
表示食物在网格的坐标。 - 当被吃到时,用
random_pos()
重新生成新的位置。
- 主循环
- 通过
clock.tick(FPS)
控制蛇每秒移动多少次。 - 监听方向键来改变蛇的方向。
- 判断蛇头和食物是否重合,若重合则得分、食物重生、蛇变长。
- 若蛇撞墙或撞自己,则游戏结束并跳转到
game_over
界面。
实现效果
总结
通过这篇文章,我们用Python+Pygame从零实现了一款简单的贪吃蛇游戏。该示例涵盖了网格移动、随机食物生成、碰撞检测、方向控制等基本概念,为你打下初步的游戏开发基础。
热门推荐
2025年无人机执照更新指南:有效期翻倍,审证要求更严
电动升降桌优缺点详解:购买前必知事项及选购建议
2025年升降桌选购指南:3大类可调高度桌子的性能评比
光遇和陌生人聊天加好友详细攻略
图说:B-4重型榴弹炮 二战苏联最有效的武器 拯救数千士兵的生命
2025广和杯龙游半程马拉松新闻发布会正式召开
华为服务器代工厂的内部构造究竟是怎样的?
如何有效利用时间管理的四象限法提高工作效率?
探索历史人物张角的真实面貌与潜在地位
CBA动态:郭艾伦重伤,女篮全明星教练出炉
白米粥和稀饭有什么区别
每天1节体育课、课间延长至15分钟——多地中小学新学期“动”起来
怎么创建网站并实现多语言支持?
宝宝冬季护理指南:从保暖到营养全方位呵护
周易第三十六卦明夷卦九三爻详解:明夷于南狩,得其大首,不可疾,贞
合肥地铁6号线开通,东部新中心迎来“黄金时代”
水清岸绿,这些美丽河涌刷新了佛山“颜值”
城市滨水空间景观规划设计方案
法眼看剧:大学生欺凌同学 在法律上如何认定?
婴幼儿家庭安全环境创设与物资配备指南
项目管理信息图怎么做
深入探讨汉字“诩”的读音、意义与自我表达的重要性
深入探讨汉字“诩”的读音、意义与自我表达的重要性
肺癌术后吃什么营养品能提高免疫力
逐梦西非的中国远洋捕捞队
哈佛神学院首次举办道教仪式:文化交流与学术探讨的新机遇
冰糖燕窝怎么吃效果最好(冰糖燕窝的炖煮技巧)
二型糖尿病前期如何治疗
授权是什么?类型、特点及实施要点全解析
眼睛视力达到1.0是否属于正常范围?了解视力标准的重要性