用Python和Pygame实现简单贪吃蛇游戏

news2024/11/19 23:32:11

1.pip安装pygame

  • pygam插件安装

pip install 插件名字    # 安装
pip uninstall 插件名字    # 卸载
pip install 插件名字 -i 指定下载的镜像网址
pip show 插件名字        # 查看插件名字

pip  install  pygame  -i https://pypi.tuna.tsinghua.edu.cn/simple
pip  show  pygame

 2.pygame入门

       详细看教程

  • 官方示例项目:https://www.pygame.org/tags/all

  • 官方开发文档:Pygame Front Page — pygame v2.6.0 documentation

3.代码

"""
# 0, 90, 180, 270
#下, 右 , 上 , 左
Snake类:
    __init__(): # 指定默认方向向右
    move(): # 让蛇根据当前方法进行移动(移动一格)
        # 当前蛇头前进的方向复制一份
        # 获取移动坐标,移动坐标更新
        # 把新的头放在最前面通过insert()
        # 把蛇尾移除掉
    draw(): # 根据移动方向,旋转舌头图片角度

Game类:
    # 合适位置移动,适当延时
"""
import random
import sys
import time

import pygame

# 全局变量
SCREEN_WIDTH = 640  # 屏幕宽度
SCREEN_HEIGHT = 480  # 屏幕高度

BLOCK_SIZE = 20  # 方格的宽、高长度

COLOR_GRAY = (150, 150, 150)  # 灰色
COLOR_GREEN = (0, 150, 0)  # 绿色
COLOR_WHITE = (255, 255, 255)  # 白色
COLOR_RED = (255, 0, 0)  # 红色

DIRECTION_MOVE = {
    pygame.K_DOWN: (0, 1),  # down
    pygame.K_RIGHT: (1, 0),  #right
    pygame.K_UP: (0, -1),  # up
    pygame.K_LEFT: (-1, 0)  # left
}
DIRECTION_HEAD_ANGLE = {
    pygame.K_DOWN: 0,
    pygame.K_RIGHT: 90,
    pygame.K_UP: 180,
    pygame.K_LEFT: 270
}


# 蛇类
class Snake:
    def __init__(self):
        # 设置初始方向为下
        self.direction = pygame.K_DOWN
        # 定义蛇身
        self.snake_body = [
            # x y 宽高
            pygame.Rect(3 * BLOCK_SIZE, 3 * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
            pygame.Rect(2 * BLOCK_SIZE, 3 * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
            pygame.Rect(1 * BLOCK_SIZE, 3 * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
        ]
        # 加载头图片
        head_img = pygame.image.load("res/head-red.png")
        # head_img = pygame.transform.rotate(head_img, 90)
        # 设置 头img的图片 和大小
        self.head_img = pygame.transform.scale(head_img, (BLOCK_SIZE, BLOCK_SIZE))

    # 回之蛇
    def draw(self, screen):
        for node in self.snake_body[1:]:
            # 绘制矩形  pygame.draw.rect(画布,颜色,node:位置和大小 边框)
            pygame.draw.rect(screen, COLOR_WHITE, node, border_radius=3)
        # 设置头 旋转
        head_img = pygame.transform.rotate(self.head_img, DIRECTION_HEAD_ANGLE[self.direction])
        # 设置头
        snake_head = self.snake_body[0]
        screen.blit(head_img, (snake_head.x, snake_head.y))

    def move(self):
        # 复制头
        new_node = self.snake_body[0].copy()
        # 确定移动方向
        pos = DIRECTION_MOVE[self.direction]
        # 更新坐标
        new_node.x += (pos[0] * BLOCK_SIZE)
        new_node.y += (pos[1] * BLOCK_SIZE)
        # 变换头部节点
        self.snake_body.insert(0, new_node)
        self.snake_body.pop()

    def check_collision(self):
        # 检查蛇头是否碰到墙壁
        # 判断蛇头是否 超出边界
        if self.snake_body[0].x < 0 or self.snake_body[0].x >= SCREEN_WIDTH or \
                self.snake_body[0].y < 0 or self.snake_body[0].y >= SCREEN_HEIGHT:
            print("死亡")
            print(f"分数为{len(self.snake_body)-3}")
            return True
        # 检查蛇头是否碰到自己的身体
        for node in self.snake_body[1:]:
            if self.snake_body[0].colliderect(node):
                print("死亡")
                print(f"分数为{len(self.snake_body)-3}")
                return True
        return False

    def is_direction_enable(self, event_key):
        # 按键方向是否合法
        # 按键不是上下左右按键,返回False
        if event_key not in DIRECTION_MOVE:
            return False
        # 如果方向为左右,同时,蛇能左右掉头,返回False
        LR = (pygame.K_RIGHT, pygame.K_LEFT)
        if event_key in LR and self.direction in LR:
            return False
        # 如果方向为上下,同时,蛇能上下掉头,返回False
        UD = (pygame.K_DOWN, pygame.K_UP)
        if event_key in UD and self.direction in UD:
            return False
        return True
        # 上面条件都进不去,返回True

    def update_direction(self, event_key):
        self.direction = event_key
        # 更新移动的方向

    def grow(self):
        node = self.snake_body[-1].copy()
        self.snake_body.append(node)


class Food():
    def __init__(self):
        # 食物的随机x, y坐标,不要超出范围
        x = random.randint(0, SCREEN_WIDTH // BLOCK_SIZE - 1)
        y = random.randint(0, SCREEN_HEIGHT // BLOCK_SIZE - 1)
        self.f_rect = pygame.Rect((x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))

    def draw(self, screen):
        pygame.draw.rect(screen, COLOR_RED, self.f_rect, border_radius=3)


class Game():
    def __init__(self, title):
        self.title = title
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption(self.title)

        self.img = pygame.image.load("res/snake_logo.png")
        pygame.display.set_icon(self.img)
        bg_image = pygame.image.load("res/bg.png")
        self.bg_img = pygame.transform.scale(bg_image, (SCREEN_WIDTH, SCREEN_HEIGHT))

    def start(self):
        s = Snake()
        f = Food()
        while True:
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYDOWN:

                    # s.direction = event.key
                    if s.is_direction_enable(event.key):
                        s.update_direction(event.key)

            self.screen.blit(self.bg_img, (0, 0))

            # ---------------绘制网格
            # 绘制所有横线 y = 640 // 20 = 24  [0, 20, 40, 60, ... 640)
            for y in range(0, SCREEN_HEIGHT, BLOCK_SIZE):
                pygame.draw.line(self.screen, COLOR_GRAY, (0, y), (SCREEN_WIDTH, y))
            # 绘制所有竖线 x = 480 // 20 = 24  [0, 20, 40, 60, ... 480)
            for x in range(0, SCREEN_WIDTH, BLOCK_SIZE):
                pygame.draw.line(self.screen, COLOR_GRAY, (x, 0), (x, SCREEN_HEIGHT))
            # 画蛇
            s.draw(self.screen)
            # 画食物
            f.draw(self.screen)

            pygame.display.update()
            if s.check_collision():
                pygame.quit()
                sys.exit()
            # 蛇移动
            s.move()
            # 判断是否吃到食物
            if s.snake_body[0] == f.f_rect:
                f = Food()
                # 身体加长
                s.grow()
            #             游戏节奏
            time.sleep(0.1)


game = Game("林安生贪吃蛇")
game.start()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1624408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

猫头虎分享已解决Error || 已解决error: subprocess-exited-with-error

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

零基础HTML教程(26)--表单元素标注

文章目录 1. 引子2. 使用标注3. 元素的id与name4. 更好的写法5. 小结 1. 引子 我们看一个表单&#xff1a; <form>姓名&#xff1a;<input type"text"><br>手机号:<input type"text"><br>年龄:<input type"text&qu…

(一)Amira入门实例

1.打开Amira安装目录下的数据Foam.am图片&#xff0c;打开之后选择“um”选项。 2. 添加一个2D和3D显示组件&#xff0c;即Ortho Slice和Volume Rendering&#xff0c;分别为2D显示和3D显示&#xff08;模块左侧绿点控制是否显示&#xff09;&#xff1a; 颜色反转之后&#xf…

web案例

一、结合抽奖案例完成随机点名程序&#xff0c;要求如下: 1.点击点名按钮&#xff0c;名字界面随机显示&#xff0c;按钮文字由点名变为停止 2.再次点击点名按钮&#xff0c;显示当前被点名学生姓名&#xff0c;按钮文字由停止变为点名 3.样式请参考css及html自由发挥完成。 二…

【学习】​CSMM和CMMI的关系你了解吗

CMMI和CSMM都是评估和提升软件组织能力成熟度的模型&#xff0c;但它们在起源、应用范围、模型结构和实施目的等方面存在一些区别。在当今竞争激烈的软件市场中&#xff0c;提升软件能力成为了多数组织追求成功的关键因素。而选择适合的体系标准能够助力企业发展得更加迅速。作…

什么是拉动经济增长的“三驾马车”

从支出法核算角度看&#xff0c;经济增长是投资、消费、净出口这三种需求之和&#xff0c;因此经济学上常把最终消费支出、资本形成总额、货物和服务净出口这三者形象地比喻为拉动经济增长的“三驾马车”。 一、指标含义 最终消费支出反映消费需求&#xff0c;可以分为居民消…

Day22 SSH远程管理服务

sshd服务&#xff0c;系统自带&#xff0c;默认开机自启运行 云/物理服务器的安全组和防火墙默认放行该端口 软件包&#xff1a;openssh-server&#xff08;服务端&#xff09;&#xff1b;openssh-client&#xff08;客户端&#xff09;&#xff1b; 格式&#xff1a;ssh I…

【kotlin】利用by关键字更加方便地实现装饰器模式

关于kotlin中的by关键字的用法&#xff0c;kotlin官方文档属性委托这一节讲得很清楚。 简单来说就是这样的&#xff0c;假设存在一个接口Component如下&#xff1a; interface Component {fun method1(): IntArrayfun method2(a: Int)fun method3(a: Int, str: String) }那么对…

【Redis 开发】缓存穿透解决

缓存穿透 缓存穿透缓存空对象布隆过滤缓存空对象实现其他缓解方式 缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存就永远不会生效&#xff0c;这些请求都会打到数据库 常见的解决方案有两种&#xff1a; 缓存空对象&#xff0c;布隆过…

某某志蓝队初级一面分享

某某志蓝队初级一面分享 所面试的公司&#xff1a;某某志 薪资待遇&#xff1a;待定 所在城市&#xff1a;河北 面试职位&#xff1a;蓝队初级 面试过程&#xff1a;我感觉面试官的语速有点点快&#xff0c;就像两个字读成一个字的那种&#xff0c;在加上我耳朵不太好&…

100-Python Django 在线电子商城

基于Django的在线电子商城开发实践 一、引言 随着互联网的快速发展&#xff0c;电子商务已经成为人们日常生活中不可或缺的一部分。在线电子商城作为电子商务的重要组成部分&#xff0c;为用户提供了便捷的购物体验。本文将以Python的Django框架为基础&#xff0c;介绍如何开…

WPS-EXCEL:快速删除多个线条对象

问题图 我需要将线条快速删除 方法一:使用定位对象功能 使用定位功能&#xff1a;按Ctrl G打开定位对话框。在对话框中&#xff0c;点击“定位条件”。 定位对象&#xff1a;在定位条件对话框中&#xff0c;勾选“对象”选项&#xff0c;然后点击“确定”。这样&#xff0c;…

4 -25

1 100个英语单词两篇六级阅读 2 cf补题&#xff1b; 3 仿b站项目看源码 debug分析业务。 上了一天课&#xff0c;晚上去健身。 物理备课&#xff0c;周六去上课腻。 五一回来毛泽东思想期末考试&#xff0c;概率论期中考试。

GoLand 2021.1.3 下载与安装

当前环境&#xff1a;Windows 8.1 x64 1 浏览器打开网站 https://www.jetbrains.com/go/download/other.html 找到 2021.1.3 版本。 2 解压 goland-2021.1.3.win.zip 到 goland-2021.1.3.win。 3 打开 bin 目录下的 goland64.exe&#xff0c;选择 Evaluate for free -- Evalu…

张大哥笔记:如何选择一个好项目?

互联网已经改变了我们的日常生活&#xff0c;使我们可以便捷地获取信息&#xff0c;更快地完成工作&#xff0c;更有效地进行沟通&#xff0c;并且可以让我们更容易地获得服务。随着技术的发展&#xff0c;互联网将继续改变我们的生活.... 有时候我们会感叹&#xff0c;互联网发…

项目上线流程(保姆级教学)

01&#xff1a;注册阿里云账户 02&#xff1a;登录阿里云 03&#xff1a;在桌面新建记事本保存个人账号密码等信息 04&#xff1a;完成重置密码 05&#xff1a;安装宝塔面板 命令行 yum install -y wget && wget -O install.sh http://download.bt.cn/install/instal…

【Qt 学习笔记】Qt常用控件 | 输入类控件 | Combo Box的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 输入类控件 | Combo Box的使用及说明 文章编号&#xff…

东北大学工程训练CNC加工中心(坤图)

东北大学加工中心&#xff08;CNC&#xff09;采用的系统为FANUC系统。 要求学生自主设计图样&#xff0c;编写GCODE文件&#xff0c;操作电脑使机床按设计路径铣出图案。 本人设计的图样为坤坤图 图为用CAD设计绘制的图样。 计算坐标&#xff0c;设计铣刀轨迹&#xff0c;得…

FPGA设计篇——波形绘制软件

FPGA设计篇——波形绘制软件 写在前面一、Visio二、TimeGen三、WaveDrom写在最后 写在前面 在FPGA设计过程中&#xff0c;经常需要编写设计文档&#xff0c;其中&#xff0c;不可缺少的就是仿真波形的绘制&#xff0c;可以直接截取Vivado或者Modelsim平台实际仿真波形&#xff…

Java面试八股之Java中==和equals()的区别

Java中和equals()的区别 操作符&#xff1a; 对于基本数据类型&#xff08;如int、char、boolean等&#xff09;&#xff0c;比较的是它们的值是否相等。 对于对象引用类型&#xff0c;比较的是两个对象的内存地址&#xff08;即是否指向同一个对象实例&#xff09;。也就是…