Python小游戏 贪吃蛇(完整版) Pygame sys time

发布于:2024-04-27 ⋅ 阅读:(23) ⋅ 点赞:(0)

需要安装pip pygame 不会私 

import random


import pygame, sys,time
# pygame.init()

# 全局变量
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.score = 0
        self.icon_direction = DIRECTION_HEAD_ANGLE[pygame.K_DOWN]
        print(self.icon_direction)
        print(DIRECTION_HEAD_ANGLE)
        self.snake_body = [  # 蛇的位置  self.snake_body.insert(0, new_node) 在第一位新增  新增完蛇头改变到新增的位置 原本第二位改变到蛇头的位置
            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)
        ]
        self.sanke_img = pygame.image.load("res/head-red.png")  # 加载蛇头图片
        self.sanke_direction = pygame.transform.rotate(self.sanke_img,self.icon_direction) # 旋转蛇头
        self.snake_head = pygame.transform.scale(self.sanke_direction,(BLOCK_SIZE,BLOCK_SIZE))  # 设置蛇头大小
    def draw(self,screen):
        for x in self.snake_body[1:]:  # 遍历初始位置  给窗口画图 跳过第一个给蛇头留位置
            pygame.draw.rect(screen,COLOR_WHITE,x,border_radius=5)  # 给窗口画图 (窗口 , 颜色 ,(x左边距离,y上边距离 ,宽,高),边框圆角  )

        snake_pos = self.snake_body[0]  # 保存初始化第一个位置
        # print(snake_pos)
        screen.blit(self.snake_head,(snake_pos.x,snake_pos.y))  # 给窗口渲染蛇头图片 坐标是初始化第一个位置 <rect(60, 60, 20, 20)>  snake_pos.x第一个 60  snake_pos.y第二个 60

    def move(self):
        # pygame.Rect.copy()  —  拷贝Rect对象
        # pygame.Rect.move()  —  移动Rect对象
        # pygame.Rect.move_ip()  —  原地移动Rect对象
        # pygame.Rect.inflate()  —  放大和缩小Rect对象的尺寸
        # pygame.Rect.inflate_ip()  —  原地放大和缩小Rect对象的尺寸
        # pygame.Rect.clamp()  —  将一个Rect对象移动到另一个Rect对象的中心
        # pygame.Rect.clamp_ip()  —  原地将一个Rect对象移动到另一个Rect对象的中心

        new_node = self.snake_body[0].copy()  # 复制一份  <rect(60, 60, 20, 20)>
        # print(new_node)
        # print(new_node.x)
        # print(new_node.y)
        pos = DIRECTION_MOVE[self.direction]    # (1, 0) 保存方向
        new_node.x += (pos[0] * BLOCK_SIZE)     # <rect(60, 60, 20, 20)>  new_node.x第一个 60  pos(1, 0) 1
        new_node.y += (pos[1] * BLOCK_SIZE)     # <rect(60, 60, 20, 20)>  new_node.y第二个 60  pos(1, 0) 0
        self.snake_body.insert(0, new_node)     # snake_body列表第一位 添加处理后的坐标 <rect(60+20, 60, 20, 20)> 列表第一位改变蛇头改变
        # print(self.snake_body)
        self.snake_body.pop()                   # 删除snake_body列表最后一项
    # 判断移动按键是否合法
    def is_direction_enable(self,event):
        if event not in DIRECTION_MOVE:   # 如果按键 没有在 上下左右范围内 则无效
            return False
        LR = (pygame.K_LEFT,pygame.K_RIGHT)  # ( 按键左 ,按键右)
        if event in LR and self.direction in LR:  # 如果按键在左右 且蛇默认方向在左右 则按键无效
            return False
        UD = (pygame.K_UP ,pygame.K_DOWN)  # ( 按键上 ,按键下)
        if event in UD and self.direction in UD:  # 如果按键在上下 且蛇默认方向在上下 则按键无效
            return False

        return True
    # 修改方向默认值
    def update_direction(self,event):
        self.direction = event  # 修改方向默认值
        self.icon_direction = DIRECTION_HEAD_ANGLE[event]  # 修改蛇头图标方向默认值
        self.sanke_direction = pygame.transform.rotate(self.sanke_img, self.icon_direction)  # 旋转蛇头
        self.snake_head = pygame.transform.scale(self.sanke_direction, (BLOCK_SIZE, BLOCK_SIZE))  # 设置蛇头大小



    def grow(self):  # 添加尾巴
        end = self.snake_body[-1].copy()  # 复制 蛇列表 最后一项
        self.snake_body.append(end)    # 追加蛇列表
        self.score += 1




# 封装随机出现的食物
class Food():
    def __init__(self):
        self.x = random.randint(0,SCREEN_WIDTH//BLOCK_SIZE - 1)  # 食物随机出现的x坐标 0~ (640//20)-1 = 31 先求出有几个格子 再乘以20就是真实坐标
        self.y = random.randint(0,SCREEN_HEIGHT//BLOCK_SIZE - 1)  # 食物随机出现的x坐标 0~(480//20)-1 = 24
        self.f_rect = pygame.Rect(self.x * BLOCK_SIZE, self.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)  # 保存食物位置
    def draw(self,screen):  # 随机生成食物方法
        pygame.draw.rect(screen,COLOR_RED,(self.x * BLOCK_SIZE, self.y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), border_radius = 5)   # 给窗口画图 (窗口 , 颜色 ,(x左边距离,y上边距离 ,宽,高),边框圆角  )




class Game():
    def __init__(self):
        pygame.init()  # 初始化
        self.screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT)) # 创建窗口 (640,480) 用一个screen变量保存 窗口对象
        pygame.display.set_caption("宝龙集团") # 给窗口添加标题
        img = pygame.image.load("res/snake_logo.png")  # 加载图标
        pygame.display.set_icon(img) # 窗口添加图标
        bg_img = pygame.image.load("res/bg.png")  # 加载背景图
        self.bg = pygame.transform.scale(bg_img,(SCREEN_WIDTH,SCREEN_HEIGHT))  # 背景图设置大小 (bg_img加载的背景图 ,(窗口宽640,窗口高480))

    def start(self): #启动方法
        s = Snake()  # 实例化 蛇初始位置类
        f = Food()  # 实例化 随机食物类
        # 获取clock
        clock = pygame.time.Clock()  # 帧率
        while True:
            events = pygame.event.get()  # 获取用户所有操作事件  (鼠标点击  键盘输入) 等
            for event in events:  # 遍历事件 进行判断 触发哪些事件
                if event.type == pygame.QUIT:  # 鼠标点击 ×号 pygame库 停止工作 关闭系统
                    pygame.quit()  # Pygame库停止工作
                    sys.exit()  # 退出系统

                elif event.type == pygame.KEYDOWN:  # 判断按键是否合法
                    # print(event.key)
                    if s.is_direction_enable(event.key):  # 判断移动按键是否合法
                        # print(event.key)
                        s.update_direction(event.key)  # 改变方向默认值


            self.screen.blit(self.bg, (0, 0))  # 给窗口渲染背景图 (背景图,(初始位置x = 0,y = 0)) 需要写在循环里,否则删除的数据不会消失
            #  显示帧率 和 得分
            fps = clock.get_fps()  # 获取 帧率
            font = pygame.font.SysFont("SimHei", 40)  # 字体类型 字体大小
            txt = font.render(f"帧率:%.2f"%fps, True, COLOR_RED)  # 帧率文字  (帧率 ture 颜色)
            self.screen.blit(txt, (0, 0))  # 窗口渲染颜色 (帧率文字 ,位置)
            txt = font.render(f"得分:{s.score}", True, COLOR_RED)  # 得分文字  (得分 ture 颜色)
            self.screen.blit(txt, (0, 60))  # 窗口渲染颜色 (得分文字 ,位置)
            for y in range(0,SCREEN_HEIGHT , BLOCK_SIZE):  # 画横线 x  range (0,480,20) = 0 20 40 ....

                # 给窗口画横线 (窗口,线的颜色(150, 150, 150 灰色),(起点位置x距离左边多远,高度位置y左上边距离多远),(终点位置x距离右边多远,高度位置y下边距离多远))
                pygame.draw.line(self.screen,COLOR_GRAY,(0,y),(SCREEN_WIDTH,y))

            for x in range(0, SCREEN_WIDTH, BLOCK_SIZE):  # 画纵线 y  range (0,640,20) = 0 20 40 ....

                # 给窗口画纵线 (窗口,线的颜色(150, 150, 150 灰色),(起点x距离左边多远,高度y左上边距离多远),(终点位置x距离右边多远,高度位置y下边距离多远))
                pygame.draw.line(self.screen, COLOR_GRAY, (x, 0), (x,SCREEN_HEIGHT ))
            s.draw(self.screen)  # 调用蛇初始位置方法 传个窗口
            f.draw(self.screen)  # 调用随机食物生成
            s.move()  # 默认向右走

            if s.snake_body[0] == f.f_rect:  # 判断头是否等于食物位置
                f = Food()  # 头等于食物位置 食物重新生成
                s.grow()  # 调用添加尾巴方法(用变量拷贝蛇列表最后一项 再使用append 追加上去)






            pygame.display.update()  # 刷新 (显示渲染的内容)

            # time.sleep(0.1)  # 游戏节奏 0.1秒触发一次

            clock.tick(10)  # 每秒10帧


g = Game()   # 实例化 贪吃蛇类
g.start()    # 启动贪吃蛇


网站公告

今日签到

点亮在社区的每一天
去签到