import pygame # 导入 Pygame 库,用于游戏开发
import random # 导入随机模块,用于生成随机数
import time # 导入时间模块,方便后续使用
# 初始化 Pygame
pygame.init()
# 设置颜色,RGB 颜色格式
white = (255, 255, 255)
black = (0, 0, 0) # 蛇:黑色
green = (0, 255, 0) # 食物:绿色
blue = (50, 153, 213) # 背景:蓝色
red = (213, 50, 80) # 提示:红色
yellow = (255, 255, 102) # 分数显示:黄色
# 游戏窗口尺寸
width = 600 # 窗口宽度
height = 400 # 窗口高度
screen = pygame.display.set_mode((width, height)) # 创建游戏窗口
pygame.display.set_caption('Snake Game') # 设置窗口标题
# 字体设置
font_style = pygame.font.SysFont("bahnschrift", 25) # 设置字体样式和大小
score_font = pygame.font.SysFont("comicsansms", 25) # 设置分数字体样式和大小
# 贪吃蛇参数
snake_block = 20 # 蛇每个部分的大小(宽和高都是20)
snake_speed = 8 # 蛇的移动速度
# 绘制蛇的函数
def our_snake(snake_block, snake_list): # 两个参数:蛇每个部分大小、一个列表(包含蛇每个部分的位置坐标)
for x in snake_list: # 遍历蛇的每个部分
pygame.draw.rect(screen, black, [x[0], x[1], snake_block, snake_block]) # 绘制每个部分为矩形
# 使用 Pygame 的 draw.rect 函数绘制矩形:
# screen:绘制的窗口。
# black:矩形的颜色:黑色。
# [x[0], x[1], snake_block, snake_block]:这个列表定义了矩形的位置和大小:
# x[0] 是矩形的左上角横坐标。
# x[1] 是矩形的左上角纵坐标。
# snake_block 是矩形的宽度和高度。
# 显示消息的函数
def message(msg, color): # msg:要显示的消息文本(字符串);color:文本的颜色(通常是一个 RGB 颜色元组)
mesg = font_style.render(msg, True, color) # 渲染消息文本
# 使用 Pygame 的 render 方法来创建一个文本表面(surface)
# font_style:之前定义的字体对象,它决定了文本的样式和大小。
# msg:这是要渲染的文本内容。
# True:这个参数表示是否抗锯齿(即使文本边缘更加平滑)。
# color:这是文本的颜色,使用传入的颜色参数。
screen.blit(mesg, [width / 6, height / 3]) # 将消息绘制到屏幕上
# screen:表示游戏窗口,在其上绘制文本。
# mesg:要绘制的文本表面。
# [width / 6, height / 3]:这是文本绘制的左上角坐标,计算方式是将窗口的宽度和高度分别除以 6 和 3,从而将文本居中显示在窗口的适当位置。
# 显示分数的函数
def display_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
screen.blit(value, [0, 0]) # 在屏幕左上角显示分数
# 显示暂停信息的函数
def display_pause_message():
pause_msg = font_style.render("Paused. Press Space to Continue", True, red)
screen.blit(pause_msg, [width / 6, height / 3]) # 在屏幕中央显示暂停信息
# 主游戏循环
def game_loop():
global clock # 确保时钟对象是全局的
game_over = False # 游戏结束标志
game_close = False # 游戏关闭标志
paused = False # 添加暂停状态
x1 = width / 2 # 蛇头的初始横坐标
y1 = height / 2 # 蛇头的初始纵坐标
x1_change = 0 # 蛇头横向移动的变化量
y1_change = 0 # 蛇头纵向移动的变化量
snake_list = [] # 存储蛇的每个部分的坐标
length_of_snake = 1 # 蛇的初始长度
score = 0 # 初始化分数
# 随机生成食物的位置:确保食物总是在有效范围内,并且不会与蛇的任何部分重叠。
food_x = round(random.randrange(0, width - snake_block) / 10.0) * 10.0
food_y = round(random.randrange(0, height - snake_block) / 10.0) * 10.0
# random.randrange(0, width - snake_block):
# 这个函数从 0 到 width - snake_block 之间随机生成一个整数。width 是游戏窗口的宽度,而 snake_block 是蛇的每个部分的大小。这样确保生成的随机值不会让食物超出游戏窗口的边界,且食物的左上角不会与蛇的部分重叠。
# / 10.0:(用来标准化:这个值将根据蛇的大小改变,此处蛇20,取10;若蛇30则取10或15)
# 将生成的随机整数除以 10.0。这是为了将随机值转换为浮点数,这样可以在后面的 round 函数中进行四舍五入处理。这个步骤也确保了食物的坐标是 10 的倍数,以便与蛇的坐标一致(因为蛇的每个部分也是 snake_block 大小的矩形)。
# round(...):
# 使用 round 函数对除以 10.0 的结果进行四舍五入。这会将值四舍五入到最接近的整数,以保证生成的 x 坐标是一个整数。
# * 10.0:(前面除以多少,这里乘以多少,将标准化的整数字符转换为像素值)
# 将四舍五入后的结果乘以 10.0,将其转换回一个 snake_block 大小的整数坐标。这确保了食物的坐标是 snake_block 的整数倍,避免与蛇的部分重叠。
while not game_over: # 主循环,直到游戏结束
while game_close: # 如果游戏关闭标志为真:玩家失败
screen.fill(blue) # 填充背景颜色
message("You Lost! Press C-Continue or Q-Quit", red) # 显示游戏结束消息
pygame.display.update() # 更新屏幕显示
for event in pygame.event.get(): # 处理事件:确保游戏能够响应玩家的操作
if event.type == pygame.KEYDOWN: # 如果按下键(检查事件类型)
if event.key == pygame.K_q: # 按下 英文Q/q 键
game_over = True # 设置游戏结束
game_close = False # 退出关闭状态,返回到主循环的外层
if event.key == pygame.K_c: # 按下 英文C/c 键
game_loop() # 重新开始游戏
for event in pygame.event.get(): # 处理游戏事件(for 循环遍历 Pygame 中的事件队列,获取所有待处理的事件)
if event.type == pygame.QUIT: # 如果关闭窗口(用户点击了窗口关闭按钮)
game_over = True # 设置游戏结束
if event.type == pygame.KEYDOWN: # 如果按下键
if event.key == pygame.K_SPACE: # 检查空格键
paused = not paused # 切换暂停状态
if not paused: # 只有在未暂停时才处理移动
if event.key == pygame.K_LEFT: # 按下左箭头
x1_change = -snake_block # 向左移动
y1_change = 0 # 不改变纵向位置
elif event.key == pygame.K_RIGHT: # 按下右箭头
x1_change = snake_block # 向右移动
y1_change = 0 # 不改变纵向位置
elif event.key == pygame.K_UP: # 按下上箭头
y1_change = -snake_block # 向上移动(y 轴:向下为正方向,向上为负方向)
# Pygame 中,y 坐标的增大表示向下移动,而减小表示向上移动。
x1_change = 0 # 不改变横向位置
elif event.key == pygame.K_DOWN: # 按下下箭头
y1_change = snake_block # 向下移动
x1_change = 0 # 不改变横向位置
if paused:
display_pause_message() # 显示暂停信息
pygame.display.update() # 更新屏幕
continue # 跳过当前循环(避免在游戏暂停时执行后续的代码,比如蛇的移动和其他游戏逻辑处理。它确保在暂停状态下,游戏的状态不会改变。)
# 检测是否撞到边界
if x1 >= width or x1 < 0 or y1 >= height or y1 < 0:
game_close = True # 碰到边界时关闭游戏
# 绘制食物、管理蛇的状态
x1 += x1_change # 更新蛇头横坐标
y1 += y1_change # 更新蛇头纵坐标
screen.fill(blue) # 填充背景颜色
pygame.draw.rect(screen, green, [food_x, food_y, snake_block, snake_block]) # 绘制食物
snake_head = [x1, y1] # 创建一个列表用于存储蛇头的坐标
snake_list.append(snake_head) # 将蛇头加入蛇的列表
if len(snake_list) > length_of_snake: # 如果蛇的长度超过当前长度
del snake_list[0] # 删除蛇尾部分
# 确保蛇的总长度始终等于 length_of_snake。在吃到食物时,蛇头会增加,而在保持长度时,蛇尾会被删除,从而看起来蛇在不断移动。
# 检测是否撞到自身
for x in snake_list[:-1]: # 切片操作,它返回列表中除 最后一个元素(蛇头)以外的所有元素
if x == snake_head: # 如果蛇头与身体部分重叠
game_close = True # 游戏关闭
our_snake(snake_block, snake_list) # 绘制蛇的函数
display_score(score) # 显示分数
pygame.display.update() # 更新屏幕显示
# 检测是否吃到食物:检查蛇头(坐标为 (x1, y1))是否与食物(坐标为 (food_x, food_y))相交
if (x1 < food_x + snake_block and x1 + snake_block > food_x and
y1 < food_y + snake_block and y1 + snake_block > food_y):
# 条件的逻辑是:
# x1 < food_x + snake_block:蛇头的左侧在食物的右侧。
# x1 + snake_block > food_x:蛇头的右侧在食物的左侧。
# y1 < food_y + snake_block:蛇头的上边在食物的下边。
# y1 + snake_block > food_y:蛇头的下边在食物的上边。
# 重新生成食物
food_x = round(random.randrange(0, width - snake_block) / 10.0) * 10.0
food_y = round(random.randrange(0, height - snake_block) / 10.0) * 10.0
length_of_snake += 1 # 蛇的长度增加
score += 1 # 更新分数
clock.tick(snake_speed) # 控制游戏速度(确保游戏在每个循环迭代中都不会太快或太慢)
# clock 对象:
# clock 是使用 pygame.time.Clock() 创建的一个时钟对象。它的主要作用是控制游戏循环的速度。
# 通过 Clock 对象,可以实现帧率的控制,使得游戏在不同的机器上能够以相同的速度运行。
# tick 方法:
# tick() 方法用于控制程序的帧率。它接收一个参数,即希望的帧率(FPS,Frames Per Second)。
# 这个方法会让程序暂停足够的时间,以确保每秒的循环次数不超过设定的帧率。
# snake_speed 参数:
# snake_speed 是一个表示蛇移动速度的变量,通常是一个整数值。这个值决定了游戏中每秒能够执行的循环次数。
# 如果 snake_speed 设置为 8,那么 tick(8) 表示希望每秒进行8次更新。换句话说,游戏的速度会根据这个值进行调整。
pygame.quit() # 退出 Pygame
quit() # 结束程序
clock = pygame.time.Clock() # 创建时钟对象,控制游戏的帧率
game_loop() # 启动游戏循环
python贪吃蛇小游戏(超详细)
最新推荐文章于 2025-06-15 22:02:27 发布