首页 前端知识 Pygame经典小游戏--贪吃蛇(完整代码 部分代码讲解)

Pygame经典小游戏--贪吃蛇(完整代码 部分代码讲解)

2025-03-08 14:03:34 前端知识 前端哥 372 699 我要收藏

     

目录

一.运行效果

二.使用说明

三.完整代码

四.代码讲解

1.按钮类:

2.游戏前选择游戏难度界面:

  2.1显示游戏名称、不同难度按钮、开始游戏按钮:

  2.2难度选择时动画:

3.游戏界面历史最高分显示:

4.游戏结束界面:

  4.1本局游戏分数、历史最高分数显示:

  4.2退出游戏和再玩一次功能实现:

五.总结


      本文的贪吃蛇小游戏根据从零开始用 Python 打造经典贪吃蛇游戏:代码+详解_pygame贪吃蛇游戏代码-CSDN博客进行改进优化,在原有的基础功能上增加了通过界面按钮可选择难度、历史最高分显示、结束游戏可选择继续游戏等功能,进一步优化了小游戏的体验感受。

一.运行效果

游戏开始界面:

游戏界面:

游戏结束界面:

二.使用说明

  首先我们打开Pycharm,没有安装的小伙伴可以看这个安装教程。新建一个项目,在项目里新建一个main.py文件,再把完整代码粘贴到main.py文件中,注意:

    ①.在终端输入以下命令安装pygame库:

pip install pygame

    ②.修改第31行的save_path为“你项目的地址/score.txt”;

再运行main.py即可。

三.完整代码

  话不多少,直接上完整代码:

import pygame
import random
import os
import sys

# 初始化 pygame
pygame.init()

# 屏幕大小
WIDTH, HEIGHT = 600, 400
CELL_SIZE = 20

# 定义颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
TURQUOISE=(187,255,255)
CYAN=(0,229,238)
CYANA=(0,255,255)

# 创建屏幕
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('贪吃蛇')

# 初始化时钟
clock = pygame.time.Clock()


#最高分保存地址
save_path = 'D:/pycharm/project/test/score.txt'

#按钮类
class Button:
    def __init__(self, text, x, y, width, height, font_size, font_color):
        self.text = text
        self.rect = pygame.Rect(x, y, width, height)
        self.font = pygame.font.Font(None, font_size)
        self.text_surf = self.font.render(self.text, True, font_color)
        self.text_rect = self.text_surf.get_rect(center=self.rect.center)

    def draw(self, screenn,bg_color):
        pygame.draw.rect(screenn, bg_color, self.rect)
        screen.blit(self.text_surf, self.text_rect)

    def is_clicked(self, pos):
        if self.rect.collidepoint(pos):
            return True

#创建按钮
play_again_button = Button('Play Again', WIDTH // 2 - 100, HEIGHT // 2 + 70, 200, 50, 30, WHITE)
game_over_button = Button('Exit', WIDTH // 2 - 100, HEIGHT // 2 + 20, 200, 50, 30, WHITE)
easy_button = Button('Easy', WIDTH // 2 - 100, HEIGHT // 2 - 50, 200, 30, 30, WHITE)
common_button = Button('Common', WIDTH // 2 - 100, HEIGHT // 2 -20, 200, 30, 30, WHITE)
difficult_button = Button('Diffcult', WIDTH // 2 - 100, HEIGHT // 2 +10, 200, 30, 30, WHITE)
play_button = Button('play', WIDTH // 2 - 100, HEIGHT // 2 +50, 200, 50, 30, WHITE)

def draw_snake(snake_body):
    """绘制蛇的身体"""
    for segment in snake_body:
        pygame.draw.rect(screen, GREEN, pygame.Rect(segment[0], segment[1], CELL_SIZE, CELL_SIZE))

def show_message(text, color, size, position):
    """显示信息"""
    font = pygame.font.Font(None, size)
    message = font.render(text, True, color)
    screen.blit(message, position)

def game():
    #初始化本局得分和最高纪录
    score=0
    maxscore=0

    # 检查score文件是否存在
    if not os.path.exists(save_path):
        with open(save_path, 'w'):
            pass
    else:
        try:
            with open(save_path, 'r') as file:
                maxscore = int(file.read().strip())
        except ValueError:
            maxscore = 0
        except FileNotFoundError:
            maxscore = 0

    #选择游戏难度界面
    rundevel = True
    nodickdevel = True
    SCR = 3
    while rundevel:
        screen.fill(BLACK)
        show_message("Greedy Snake", RED, 50, (WIDTH // 2 - 110, HEIGHT // 2 - 130))
        easy_button.draw(screen,TURQUOISE)
        common_button.draw(screen,TURQUOISE)
        difficult_button.draw(screen,TURQUOISE)
        play_button.draw(screen,GREEN)
        pygame.display.flip()
        if nodickdevel == True:
            if easy_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, CYAN)
                common_button.draw(screen, TURQUOISE)
                difficult_button.draw(screen, TURQUOISE)
                pygame.display.flip()
            elif common_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, TURQUOISE)
                common_button.draw(screen, CYAN)
                difficult_button.draw(screen, TURQUOISE)
                pygame.display.flip()
            elif difficult_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, TURQUOISE)
                common_button.draw(screen, TURQUOISE)
                difficult_button.draw(screen, CYAN)
                pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if easy_button.is_clicked(event.pos):
                    SCR =0
                    movespeed=4
                    nodickdevel=False
                elif common_button.is_clicked(event.pos):
                    SCR=1
                    movespeed=7
                    nodickdevel = False
                elif difficult_button.is_clicked(event.pos):
                    SCR=2
                    movespeed = 10
                    nodickdevel = False
                elif play_button.is_clicked(event.pos) and (SCR==0 or SCR==1 or SCR==2):
                    rundevel=False
        if SCR==0:
            easy_button.draw(screen, CYANA)
            common_button.draw(screen, TURQUOISE)
            difficult_button.draw(screen, TURQUOISE)
            pygame.display.flip()
        elif SCR==1:
            easy_button.draw(screen, TURQUOISE)
            common_button.draw(screen, CYANA)
            difficult_button.draw(screen, TURQUOISE)
            pygame.display.flip()
        elif SCR==2:
            easy_button.draw(screen, TURQUOISE)
            common_button.draw(screen, TURQUOISE)
            difficult_button.draw(screen, CYANA)
            pygame.display.flip()
        clock.tick(30)

    # 初始化蛇
    snake_pos = [100, 40]  # 蛇头初始位置
    snake_body = [[100, 40], [80, 40], [60, 40]]  # 蛇身体
    direction = 'RIGHT'  # 蛇头初始方向
    change_to = direction

    # 初始化食物
    food_pos = [random.randrange(1, WIDTH // CELL_SIZE) * CELL_SIZE,
                random.randrange(1, HEIGHT // CELL_SIZE) * CELL_SIZE]
    food_spawn = True

    #游戏进行界面
    running = True
    while running:
        # 监听按键事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP and direction != 'DOWN':
                    change_to = 'UP'
                elif event.key == pygame.K_DOWN and direction != 'UP':
                    change_to = 'DOWN'
                elif event.key == pygame.K_LEFT and direction != 'RIGHT':
                    change_to = 'LEFT'
                elif event.key == pygame.K_RIGHT and direction != 'LEFT':
                    change_to = 'RIGHT'

        direction = change_to

        # 更新蛇头位置
        if direction == 'UP':
            snake_pos[1] -= CELL_SIZE
        elif direction == 'DOWN':
            snake_pos[1] += CELL_SIZE
        elif direction == 'LEFT':
            snake_pos[0] -= CELL_SIZE
        elif direction == 'RIGHT':
            snake_pos[0] += CELL_SIZE

        # 增加蛇头
        snake_body.insert(0, list(snake_pos))

        # 检测是否吃到食物
        if snake_pos == food_pos:
            score += 10  # 更新分数
            food_spawn = False
        else:
            snake_body.pop()

        # 刷新食物位置
        if not food_spawn:
            food_pos = [random.randrange(1, WIDTH // CELL_SIZE) * CELL_SIZE,
                        random.randrange(1, HEIGHT // CELL_SIZE) * CELL_SIZE]
            food_spawn = True

        # 游戏结束条件
        if (
            snake_pos[0] < 0 or snake_pos[0] >= WIDTH or
            snake_pos[1] < 0 or snake_pos[1] >= HEIGHT
        ):
            running = False

        # 检测蛇是否碰到自己
        for block in snake_body[1:]:
            if snake_pos == block:
                running = False

        # 绘制屏幕
        screen.fill(BLACK)
        draw_snake(snake_body)
        pygame.draw.rect(screen, RED, pygame.Rect(food_pos[0], food_pos[1], CELL_SIZE, CELL_SIZE))
        show_message(f'Score: {score}', WHITE, 20, (10, 10))  # 确保每次循环都更新分数显示
        show_message(f'Max_score: {maxscore}', WHITE, 20, (490, 10))
        pygame.display.update()
        clock.tick(movespeed)

    #游戏结束界面
    run=True
    while run:
        # 游戏结束信息
        if score>maxscore:
            with open(save_path, 'w') as file:
                file.write(str(score))
        screen.fill(BLACK)
        show_message("Game Over!", RED, 50, (WIDTH // 2 - 110, HEIGHT // 2 - 130))
        show_message(f"Your Score: {score}", WHITE, 30, (WIDTH // 2 - 100, HEIGHT // 2 -80))
        show_message(f"History MaxScore: {maxscore}", WHITE, 30, (WIDTH // 2 - 100, HEIGHT // 2-30))
        play_again_button.draw(screen,GREEN)
        game_over_button.draw(screen,RED)
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if play_again_button.is_clicked(event.pos):
                    game()
                    run=False
                if game_over_button.is_clicked(event.pos):
                    pygame.quit()
                    run=False

if __name__ == "__main__":
    game()

四.代码讲解

1.按钮类:

  增加按钮类,用于按钮创建,定义显示按钮函数draw和检查点是否在按钮內函数is_clicked。

class Button:
    def __init__(self, text, x, y, width, height, font_size, font_color):
        self.text = text
        self.rect = pygame.Rect(x, y, width, height)
        self.font = pygame.font.Font(None, font_size)
        self.text_surf = self.font.render(self.text, True, font_color)
        self.text_rect = self.text_surf.get_rect(center=self.rect.center)

    def draw(self, screenn,bg_color):
        pygame.draw.rect(screenn, bg_color, self.rect)
        screen.blit(self.text_surf, self.text_rect)

    def is_clicked(self, pos):
        if self.rect.collidepoint(pos):
            return True

2.游戏前选择游戏难度界面:

  2.1显示游戏名称、不同难度按钮、开始游戏按钮:

show_message("Greedy Snake", RED, 50, (WIDTH // 2 - 110, HEIGHT // 2 - 130))
easy_button.draw(screen,TURQUOISE)
common_button.draw(screen,TURQUOISE)
difficult_button.draw(screen,TURQUOISE)
play_button.draw(screen,GREEN)

  2.2难度选择时动画:

    效果一:当鼠标移到难度按钮上时,鼠标所在按钮背景颜色加深。nodickdevel用于实现鼠标点击某个难度按钮后再移动鼠标时,不会产生效果一。

            if easy_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, CYAN)
                common_button.draw(screen, TURQUOISE)
                difficult_button.draw(screen, TURQUOISE)
                pygame.display.flip()
            elif common_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, TURQUOISE)
                common_button.draw(screen, CYAN)
                difficult_button.draw(screen, TURQUOISE)
                pygame.display.flip()
            elif difficult_button.is_clicked(pygame.mouse.get_pos()):
                easy_button.draw(screen, TURQUOISE)
                common_button.draw(screen, TURQUOISE)
                difficult_button.draw(screen, CYAN)
                pygame.display.flip()

    效果二:当鼠标点击不同难度按钮时,该难度按钮背景颜色锁定。SCR用于实现锁定后的按钮背景颜色显示;movespeed用于控制游戏时屏幕刷新快慢,即蛇移动快慢;

            elif event.type == pygame.MOUSEBUTTONDOWN:
                if easy_button.is_clicked(event.pos):
                    SCR =0
                    movespeed=4
                    nodickdevel=False
                elif common_button.is_clicked(event.pos):
                    SCR=1
                    movespeed=7
                    nodickdevel = False
                elif difficult_button.is_clicked(event.pos):
                    SCR=2
                    movespeed = 10
                    nodickdevel = False
                elif play_button.is_clicked(event.pos) and (SCR==0 or SCR==1 or SCR==2):
                    rundevel=False
        if SCR==0:
            easy_button.draw(screen, CYANA)
            common_button.draw(screen, TURQUOISE)
            difficult_button.draw(screen, TURQUOISE)
            pygame.display.flip()
        elif SCR==1:
            easy_button.draw(screen, TURQUOISE)
            common_button.draw(screen, CYANA)
            difficult_button.draw(screen, TURQUOISE)
            pygame.display.flip()
        elif SCR==2:
            easy_button.draw(screen, TURQUOISE)
            common_button.draw(screen, TURQUOISE)
            difficult_button.draw(screen, CYANA)
            pygame.display.flip()

3.游戏界面历史最高分显示:

show_message(f'Max_score: {maxscore}', WHITE, 20, (490, 10))

4.游戏结束界面:

  4.1本局游戏分数、历史最高分数显示:

        show_message(f"Your Score: {score}", WHITE, 30, (WIDTH // 2 - 100, HEIGHT // 2 -80))
        show_message(f"History MaxScore: {maxscore}", WHITE, 30, (WIDTH // 2 - 100, HEIGHT // 2-30))

  4.2退出游戏和再玩一次功能实现:

    此处逻辑很清晰,点击退出游戏直接全部退出,点击再玩一次再次运行游戏总函数game()。

            elif event.type == pygame.MOUSEBUTTONDOWN:
                if play_again_button.is_clicked(event.pos):
                    game()
                    run=False
                if game_over_button.is_clicked(event.pos):
                    pygame.quit()
                    run=False

五.总结

  通过本次对贪吃蛇游戏的改进和优化,提升了游戏的可玩性和趣味性,为玩家带来更加丰富和多样的游戏体验。如果你也对这款游戏感兴趣,不妨自己动手尝试一下,相信你会在编程的过程中找到无尽的乐趣和成就感!

转载请注明出处或者链接地址:https://www.qianduange.cn//article/22948.html
标签
pygame
评论
发布的文章

Lua与Unity交互

2025-03-08 14:03:36

Pygame介绍与游戏开发

2025-03-08 14:03:36

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!