python贪吃蛇小游戏(超详细)

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()  # 启动游戏循环

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值