python贪吃蛇小游戏,面向对象设计模式,附带源码以及所需素材

2023-11-18

在python中通过面向对象设计模式来实现一个贪吃蛇小游戏

源码在最下方,上传的资源包内也包括代码源文件以及所需素材等,源文件在game文件夹内,exe文件可直接运行,pygame模块需要自行下载

先来看运行效果图:

开始界面,点击按钮开始游戏

游戏内界面,吃掉食物增加长度,蛇头出界或撞到身体部分则游戏失败 

结算界面,显示当前成绩和历史最高分,点击按钮重来

 测试功能:游戏内按下空格键强制死亡

然后说我的设计思路,主要依靠的是pygame的精灵以及精灵组碰撞,我这里总共创建了十个类

  • BaseSprite类  基本精灵类,用作玩家类,食物类等的父类

  • Food  食物类

  • FoodManage  食物管理类,用于管理食物类

  • PlayerSprite  玩家类

  • PlayerManage  玩家管理类,分为蛇身和蛇头,实现移动,吃食物等方法

  • UISprite  UI类

  • UIMange  UI管理类,有三个UI界面,开始前,游戏中,结束

  • AudioManage  声音管理类,按钮点击,背景音乐,死亡音效,吃掉食物音效

  • Util  鼠标点击检测,用于检测用户是否点击了开始或重来按钮

  • GameManage  总管理类

下面是源代码部分

import random
import time
import pygame
import sys


class Util:
    """
    鼠标点击碰撞检测
    """

    @staticmethod
    def click_check(sprite):
        if pygame.mouse.get_pressed()[0]:
            if sprite.rect.collidepoint(pygame.mouse.get_pos()):
                return True
        return False


class AudioManage:
    """
    声音管理类
    """

    @staticmethod
    def play_bg_music():
        """
        背景音乐
        """
        pygame.mixer.music.load("../sound/bgm.wav")
        pygame.mixer.music.play(True)

    @staticmethod
    def play_sound(name):
        sound = pygame.mixer.Sound(name)
        sound.play()


class BaseSprite(pygame.sprite.Sprite):
    """
    基本精灵类, 有name属性, 就是精灵的图片路径
    """

    def __init__(self, name):
        super().__init__()
        self.image = pygame.image.load(name)
        self.rect = self.image.get_rect()


class Food(BaseSprite):
    """
    食物类
    """

    def __init__(self, name, center):
        super().__init__(name)
        self.rect.center = center


class PlayerSprite(Food):
    """
    玩家类(蛇头, 蛇身)
    """

    def __init__(self, name, center):
        super().__init__(name, center)


class UISprite(Food):
    """
    ui类
    """

    def __init__(self, name, center):
        super().__init__(name, center)


class FoodManage:
    """
    食物管理类
    """

    def __init__(self, gm):
        self.gm = gm
        self.food_groups = pygame.sprite.Group()

    def update(self):
        self.food_groups.update()
        self.food_groups.draw(self.gm.screen)

    def clear(self):
        self.food_groups.empty()

    def add_food(self):
        self.food = Food("../image/food.png", (random.randrange(25, 575, 25), random.randrange(25, 575, 25)))
        self.food.add(self.food_groups)


class PlayerManage:
    """
    玩家管理类
    """

    def __init__(self, gm):
        self.gm = gm
        self.player_groups = pygame.sprite.Group()
        self.body_groups = pygame.sprite.Group()
        AudioManage.play_bg_music()

    def born(self):
        self.mk_dir = "left"
        self.player = PlayerSprite("../image/left.png", (500, 500))
        self.player.add(self.player_groups)

        for i in range(3):
            self.body = PlayerSprite("../image/body.png", (500 + 25 * (i + 1), 500))
            self.body.add(self.body_groups)

        for i in range(3):
            self.food = Food("../image/food.png", (random.randrange(25, 575, 25), random.randrange(25, 575, 25)))
            self.food.add(self.gm.food_manage.food_groups)

        pygame.time.set_timer(6666, 100)

    def update(self):
        self.player_groups.update()
        self.body_groups.update()
        self.player_groups.draw(self.gm.screen)
        self.body_groups.draw(self.gm.screen)

    def clear(self):
        self.player_groups.empty()
        self.body_groups.empty()

    def move(self, dir):
        first = self.player.rect.center
        last = self.body.rect.center
        for i in range(len(self.body_groups.sprites()) - 1, 0, -1):
            self.body_groups.sprites()[i].rect.center = self.body_groups.sprites()[i - 1].rect.center
        self.body_groups.sprites()[0].rect.center = first

        self.mk_dir = dir
        if self.mk_dir == "up":
            self.player.image = pygame.image.load("../image/up.png")
            self.player.rect.centery -= 25
        elif self.mk_dir == "down":
            self.player.image = pygame.image.load("../image/down.png")
            self.player.rect.centery += 25
        elif self.mk_dir == "left":
            self.player.image = pygame.image.load("../image/left.png")
            self.player.rect.centerx -= 25
        elif self.mk_dir == "right":
            self.player.image = pygame.image.load("../image/right.png")
            self.player.rect.centerx += 25

        if pygame.sprite.spritecollide(self.player, self.gm.food_manage.food_groups, True):
            AudioManage.play_sound("../sound/eat.mp3")
            self.eat(last)
            self.gm.food_manage.add_food()
        if pygame.sprite.spritecollide(self.player, self.body_groups, False):
            AudioManage.play_sound("../sound/die.wav")
            self.gm.state = "end"
            pygame.time.set_timer(6666, 0)

        if self.player.rect.left < 0 or self.player.rect.right > 600 or self.player.rect.top < 0 or self.player.rect.bottom > 600:
            AudioManage.play_sound("../sound/die.wav")
            self.gm.state = "end"
            pygame.time.set_timer(6666, 0)

    def eat(self, center):
        self.body = PlayerSprite("../image/body.png", center)
        self.body.add(self.body_groups)
        self.gm.ui_manage.score += 5
        if self.gm.ui_manage.score > self.gm.ui_manage.max_score:
            self.gm.ui_manage.max_score = self.gm.ui_manage.score
        self.gm.ui_manage.gaming_surface = self.gm.ui_manage.font.render(f"得分:{self.gm.ui_manage.score}", True,
                                                                         (0, 0, 0))


class UIMange:
    """
    ui管理类
    """

    def __init__(self, gm):
        self.gm = gm
        self.max_score = 0
        self.score = 0
        self.font = pygame.font.Font(r"../font/simkai.ttf", 32)
        # 开始前
        self.start_groups = pygame.sprite.Group()
        self.start_btn = UISprite("../image/begin_btn.png", (300, 300))
        self.start_btn.add(self.start_groups)

        # 游戏中
        self.gaming_surface = self.font.render(f"得分:{self.score}", True, (0, 0, 0))

        # 结束
        self.end_groups = pygame.sprite.Group()
        self.end_btn = UISprite("../image/replay_btn.png", (300, 300))
        self.end_btn.add(self.end_groups)

    def update(self):
        if self.gm.state == "ready":
            self.start_groups.draw(self.gm.screen)
            if Util.click_check(self.start_btn):
                AudioManage.play_sound("../sound/click.mp3")
                self.gm.state = "gaming"
                self.gm.player_manage.born()
        if self.gm.state == "gaming":
            self.gm.screen.blit(self.gaming_surface, (400, 20))
        if self.gm.state == "end":
            self.final_score = self.font.render(f"最终得分:{self.score}", True, (0, 0, 0))
            self.final_max_score = self.font.render(f"最高分:{self.max_score}", True, (0, 0, 0))
            self.gm.screen.blit(self.final_score, (200, 150))
            self.gm.screen.blit(self.final_max_score, (200, 100))
            self.gm.player_manage.clear()
            self.gm.food_manage.clear()
            self.end_groups.draw(self.gm.screen)
            if Util.click_check(self.end_btn):
                self.gm.dir = "left"
                AudioManage.play_sound("../sound/click.mp3")
                self.gm.player_manage.born()
                self.gm.state = "gaming"
                self.score = 0
                self.gaming_surface = self.font.render(f"得分:{self.score}", True, (0, 0, 0))


class GameManage:
    """
    游戏管理类(总管理类)
    """

    def __init__(self, name):
        pygame.init()
        self.screen = pygame.display.set_mode((600, 600))
        self.clock = pygame.time.Clock()
        self.state = "ready"
        self.ui_manage = UIMange(self)
        self.player_manage = PlayerManage(self)
        self.food_manage = FoodManage(self)
        self.dir = "left"
        pygame.display.set_caption(name)

    def check_move(self):
        if self.player_manage.mk_dir == "left" and self.dir == "right" or self.player_manage.mk_dir == "right" and self.dir == "left" or self.player_manage.mk_dir == "up" and self.dir == "down" or self.player_manage.mk_dir == "down" and self.dir == "up":
            return False
        else:
            return True

    def check_event(self):
        for event in pygame.event.get():
            if event.type == 256:
                pygame.quit()
                sys.exit()

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_SPACE:
                    self.state = "end"

            # 键盘控制移动
            if self.state == "gaming":
                if event.type == 6666:
                    if self.check_move():
                        self.player_manage.move(self.dir)
                    else:
                        self.player_manage.move(self.player_manage.mk_dir)
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP and self.dir != "up":
                        self.dir = "up"
                    elif event.key == pygame.K_DOWN and self.dir != "down":
                        self.dir = "down"
                    elif event.key == pygame.K_LEFT and self.dir != "left":
                        self.dir = "left"
                    elif event.key == pygame.K_RIGHT and self.dir != "right":
                        self.dir = "right"
                    time.sleep(0.05)

    def run(self):
        while True:
            if pygame.mixer.music.get_busy() == False:
                AudioManage.play_bg_music()
            self.clock.tick(50)
            self.check_event()
            self.screen.fill("#FFFACD")
            self.ui_manage.update()
            self.player_manage.update()
            self.food_manage.update()

            pygame.display.flip()


gm = GameManage("贪吃蛇大作战")

if __name__ == '__main__':
    gm.run()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python贪吃蛇小游戏,面向对象设计模式,附带源码以及所需素材 的相关文章

  • 解析lxml.etree._Element内容

    我从以下元素中解析出 table td align center valign top a href ConfigGroups aspx cfgID 451161 amp prjID 11778 amp grpID DTST target
  • 如何从本地模式下运行的 pyspark 中的 S3 读取数据?

    我正在使用 PyCharm 2018 1 使用 Python 3 4 并通过 virtualenv 中的 pip 安装 Spark 2 3 本地主机上没有安装hadoop 因此没有安装Spark 因此没有SPARK HOME HADOOP
  • Cython 回调适用于函数,但不适用于绑定方法

    我正在实现一个基于 cython 的 C 库接口 我实现了一个回调系统 它可以与普通函数一起使用 但在传入绑定方法时会奇怪地失败 这是我的 cython 代码的一部分 cdef extern from VolumeHapticTool h
  • 打乱列表并返回副本

    我想对数组进行洗牌 但我找到的只是类似的方法random shuffle x from 在 Python 中随机化字符串列表的最佳方法 https stackoverflow com questions 1022141 best way t
  • 如何获取Python对象父级?

    所以 我试图获取自定义对象 内部 的对象 这是一个例子 假设 o 是一个对象 无论是什么类型 它都可以存储变量 o Object class Test def init self self parent o This is where I
  • 执行不区分大小写的“in”检查并检索原始元素的最简单方法?

    假设 a 有一个字符串列表和一个特定字符串 particular string latitude list Id PRICE LATitude longitude 我想要实现的是执行不区分大小写的检查特定字符串是否在列表中 所以现在我可以这
  • 字符串中数字的连续相加

    我是一名正在学习 python 的新程序员 并且在如何完成此任务方面遇到了困难 所以本质上我有一个从文件导入的数字字符串需要读取 并且需要将第一个数字的总和添加到第二个数字并将其转换为正确的 ascii 字符 因此 例如 如果我正在读取字符
  • xlwt 可以在单元格中创建一个包含标题和链接变量的超链接吗?

    例如 如何更改以下行 使 test 为变量 T 且 http google com http google com 是变量L ws write 0 0 xlwt Formula test HYPERLINK http google com
  • 组内条件计数

    我想在之后进行条件计数groupby 例如 按列的值分组A 然后计算每组中值出现的频率5出现在列中B 如果我整个过程都这样做DataFrame 只是len df df B 5 所以我希望我能做到df groupby A df B 5 siz
  • 无法启动 Windows 快捷方式

    我正在尝试使用 python 启动 Windows 我已经尝试了 os system subprocess call os startfile 等多种方法 但总是收到错误消息 指出路径不存在 我知道路径是正确的 因为我尝试在 CMD EXE
  • 使用 python3 查找表情符号的宽度

    我尝试使用 python 中的模式打印字母 A def printA length height symbol a for i in range length for i in range height for i in range hei
  • 初始化整数变量以进行比较

    我正在学习麻省理工学院的开放课件课程计算机科学和 Python 编程简介 https ocw mit edu courses electrical engineering and computer science 6 0001 introd
  • XGBoostLibraryNotFound:在候选路径中找不到 XGBoost 库,您是否安装了编译器并在根路径中运行了 build.sh?

    我在移动 XGBoost 的 python package 目录时遇到这个问题 Traceback most recent call last File setup py line 19 in LIB PATH libpath find l
  • 如何在Python Selenium中获取WebElement的类名?

    我使用 Selenium WebDriver 来抓取从网页中获取的 用 JavaScript 编写的表格 我正在迭代表行列表 每行可能属于不同的类别 我想获取此类的名称 以便我可以为每一行选择适当的操作 table body table f
  • 获取SVG绘图的边界框

    我想提取 SVG 绘图的边界框 由于 Python 已经在系统上可用并且还用于执行其他任务 因此我不想使用 JavaScript 或任何其他语言 我的理解是是否可以计算单个元素的边界框 但我不知道如何计算 整个绘图的边界框只是所有元素的最小
  • 禁用或限制 /o/applications(django rest 框架、oauth2)

    我目前正在使用 Django Rest 框架编写 REST API 并使用 oauth2 进行身份验证 使用 django oauth toolkit 我对他们俩都很满意 他们做的正是我想要的 然而 我有一个担忧 我正在将我的应用程序传递到
  • Django 自定义文件存储系统

    我有一个自定义存储 import os from django core files storage import Storage class AlwaysOverwriteFileSystemStorage Storage def get
  • 2D 矩阵上的 Numpy where()

    我有一个像这样的矩阵 t np array 1 2 3 foo 2 3 4 bar 5 6 7 hello 8 9 1 bar 我想获取行包含字符串 bar 的索引 在一维数组中 rows np where t bar 应该给我索引 0 3
  • 将连续行与相同的列值合并

    我有一个看起来像这样的东西 我该如何处理 0 d 0 The DT 1 Skoll ORGANIZATION 2 Foundation ORGANIZATION 3 4 based VBN 5 in IN 6 Silicon LOCATIO
  • 在Python中设置Windows命令行终端标题

    我在 Windows 计算机上运行某个 Python 脚本的多个实例 每个实例都来自不同的目录并使用单独的 shell 窗口 不幸的是 Windows 为每个 shell 窗口提供了相同的名称

随机推荐

  • 杯子

    杯子 题目描述 小明买了N个容积可以是无穷大的杯子 刚开始的时候每个杯子里有1升水 接着小明发现杯子实在太多了 于是他决定保留不超过K个杯子 每次他选择两个当前含水量相等的杯子 把一个杯子的水全部倒进另一个里 然后把空瓶丢弃 不能丢弃有水的
  • 系统烧写方法(MfgTool烧写工具)

    目录 MfgTool 工具简介 MfgTool 工作原理简介 USB接线 系统烧写原理 烧写NXP 官方系统 烧写自制的系统 系统烧写 网络开机自启动设置 改造我们自己的烧写工具 改造MfgTool 烧写测试 解决Linux 内核启动失败
  • JDK8新特性----lambda表达式

    一 Lambda表达式 1 Lambda表达式 注意 函数式接口 接口中只有一个抽象方法 参数1 参数2 抽象方法的参数 gt 分隔符 表示抽象方法的实现 1 lambda基本用法 package com wt practice lx01
  • Java 反射机制(二)

    前言 在上篇 Java 反射机制 一 介绍了一些 Java 反射相关的常用 API 在知道了如何去使用反射之后 作为一个合格的工程师 下一步肯定是要去了解它的如何实现的 我们今天就来看看在 JDK 源码中是如何去实现反射的 PS 以下源码分
  • docker查看mysql日志_如何查看docker运行日志

    查看docker运行日志的方法介绍 docker attach命令 docker attach options 容器会连接到正在运行的容器 然后将容器的标准输入 输出和错误流信息附在本地打印出来 命令中options的取值有三种 detac
  • 护网蓝队(初级)

    护网蓝队 初级 主要是会看各种攻击payload 注意常见的payload 练习各种漏洞的利用方法 学会看利用漏洞的请求长什么样 payload长什么样 payload长什么样 给个请求包 能不能认出来是攻击流量 是的话是什么漏洞的利用 蓝
  • 树09--二叉树的下一个结点

    树09 二叉树的下一个结点 jz57 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 给定一个二叉树其中的一个结点 请找出中序遍历顺序的下一个结点并且返回 注意 树中的结点不仅包含左右子结点 同时包含指向父结点的next指针
  • Qt 信号连接多个槽函数 执行顺序

    执行顺序 同一信号连接多个槽呢 槽函数执行没有绝对的先后顺序 如 connect slider QSlider valueChanged spin box QSpinBox setValue connect slider QSlider v
  • 读研期间小论文投稿-个人总结

    我是2014级研究生 学校只是一个普通211 而且工科很弱 导师对我是放养 让我回忆下 上学期就见过她一次 而且她快退休了 没项目没经费没权利 但我觉得跟着她还挺好 因为我可以自己研究自己喜欢的 没人妨碍 但同时导师没有基金 所以我的小论文
  • 两个linux服务器间复制文件

    scp是secure copy的简写 用于在Linux下进行远程拷贝文件的命令 和它类似的命令有cp 不过cp只是在本机进行拷贝不能跨服务器 1 命令格式 scp 参数 原路径 目标路径 2 命令实例 从本地服务器复制到远程服务器 1 复制
  • Vue使用Swiper看这一篇就够了

    Vue使用Swiper看这一篇就够了 此案例实现需求 完成swiper动态异步数据下的slide渲染 自定义分页器样式 解决loop true设置时的事件丢失问题 swiper鼠标移入 移出 暂停 开始轮播 单页面渲染多个swiper组件互
  • 什么是区块链概念

    区块链到底有什么价值 区块链技术被称为价值互联网 大体上原因在于它解决了原有互联网的三个基本问题 第一 区块链通过在数字货币领域的应用 提供了资金流 或者叫资本流 信息在互联网的流动的解决方案 第二 区块链通过加密和分布式账本的引用 解决了
  • 关于Visual Studio 不支持x64 内联汇编分析

    记录一下今天的大坑 实在是有必要记录一下 调程序发现参数在函数传递时 出现了异常的值 已经确认不是指针破坏的问题 用汇编看了下 发现汇编寄存器地址都取错了 在release开启o2优化时出现 关掉又正常 实在是百思不得其解 对于内联汇编 其
  • Mysql根据拼音首字母分组和排序

    最近业务上有个需求 需要根据英文字母展示对应的人名 和我们手机的通讯录差不多 如下图所示 通常如果表设计的时候增加了对应的首字母字段应该很好实现 那如果没加 应该怎么实现呢 图示Sql SELECT name ELT INTERVAL CO
  • Java FileOutputStream类

    文章目录 总结 FileOutputStream类数据结构 FileOutputStream类方法 构造方法 操作方法 总结 FileOutputStream类用于将数据写入文件或文件描述符的输出流 FileOutputStream用于写入
  • 如何查看局域网内所有IP

    要如何查看局域网内正在使用的电脑的IP一共分以下几个步骤 第一步 点击电脑左下角的 开始 然后再点击 运行 第二步 在运行窗口里填入 cmd 然后点击确定 第三步 在cmd命令窗口输入 ipconfig ALL 命令 点击键盘上的回车键 第
  • 2021年字节跳动+京东+美团面试总结!内含福利

    开篇 说一下我大概的情况 渣本毕业 工作已经有快3年了 从高中就开始玩小破站 无论是学习还是日常放松都是在b站 大学主学的软件技术专业 所以 入职bilibili是我大学时期给自己定的小目标 在学校 专业学的算中上的水平 课本知识和老师讲的
  • delphi with do和for do语句

    1 with 对象名 do语句只是为了减少输入的字符 不必每次重复名字 直接写变量 procedure TForm1 Button1Click Sender TObject 正常写法beginedit1 text hello edit1 c
  • J1939协议与CAN2.0对应关系

  • python贪吃蛇小游戏,面向对象设计模式,附带源码以及所需素材

    在python中通过面向对象设计模式来实现一个贪吃蛇小游戏 源码在最下方 上传的资源包内也包括代码源文件以及所需素材等 源文件在game文件夹内 exe文件可直接运行 pygame模块需要自行下载 先来看运行效果图 开始界面 点击按钮开始游