其他分享
首页 > 其他分享> > pygame学习日记——贪吃猪(蛇)

pygame学习日记——贪吃猪(蛇)

作者:互联网

新手向——pygame实现贪吃蛇小游戏

猪头图片由一只可爱的灵魂画家提供

贪吃蛇主要逻辑是蛇的头部带动身体移动,所以移动操作时,只需要更新头部的位置信息,而蛇身的每一块位置则更替为前一块的位置。使用列表存储蛇(蛇的头部和身体块分别由一对坐标表示),列表的第一个元素即为蛇头,对于每一次移动,采用生成新的位置坐标插入到列表的首位充当新的头部,并将列表的最后一个元素丢弃,实现蛇身每一块的前移。完整代码如下:

详细注释源码

import pygame
import sys
import random

#定义用来表示移动方向的常量(Python中并没有提供定义常量的保留字)
UP = 'move_up'
DOWN = 'move_down'
LEFT = 'move_left'
RIGHT = 'move_right'
#初始化pygame 关于init()函数相关信息见https://blog.csdn.net/Enderman_xiaohei/article/details/88655432
pygame.init()
#加载头部,身体和食物的图片
image_head = pygame.image.load("src/head.png")
image_body = pygame.image.load("src/body.png")
image_food = pygame.image.load("src/food.png")
#设置格子单位,后面的移动操作都是以此最单位进行
unit = image_body.get_width()
#设置游戏窗体尺寸
frame_size = width, height = 40,20
#生成游戏窗口
screen = pygame.display.set_mode((frame_size[0]*unit, frame_size[1]*unit))
#设置窗体标题
pygame.display.set_caption("贪吃猪")
#设置游戏图标
pygame.display.set_icon(image_head)
#加载字体
font_score = pygame.font.Font("src/font.ttf",24)
font_start = pygame.font.Font("C:/Windows/Fonts/HGCY_CNKI.TTF",48)
#用于设置游戏画面刷新帧数
clock = pygame.time.Clock()


#食物生成函数,需要传入蛇
def gen(snack):
    while True:
        #随机生成食物的坐标
        x = random.randrange(1, frame_size[0] - 1) * unit
        y = random.randrange(1, frame_size[1] - 1) * unit
        #用来标志生成的食物是否于蛇重叠
        repeat = False
        for each in snack:
            #判断是否重叠,如果重叠就将repeat标识设置为True,重新生成食物
            if x == each[0] and y == each[1]:
                repeat = True
        #不重叠就返回食物坐标
        if not repeat:
            return [x, y]


#移动函数,需要传入移动方向和蛇
def move(direction,snack):
    newhead = []
    #声明unit是全局变量
    global unit
    #生成新的头部
    newhead.append(snack[0][0])
    newhead.append(snack[0][1])
    #根据传入的方向设置新头部的移动
    if direction == UP:
        newhead[1] -= unit
    elif direction == DOWN:
        newhead[1] += unit
    elif direction == RIGHT:
        newhead[0] += unit
    elif direction == LEFT:
        newhead[0] -= unit
    #将新的头部插到列表的首位,并移除snake列表的最后一个元素,实现蛇的整体移动
    #移动的本质时头部带动身体,每一块身体移动到前一块身体的位置
    snack.insert(0,newhead)
    snack.pop()
    #返回移动过的蛇
    return snack


#游戏开始界面,随便写的,可以忽略
def gamestart():
    global unit,frame_size
    speed_start = [1, 1]
    speed_exit = [1, 1]
    text_start = font_start.render("开始游戏", True, (255, 0, 0))
    text_start_rect = text_start.get_rect()
    text_exit = font_start.render("退出游戏", True, (255, 0, 0))
    text_exit_rect = text_exit.get_rect()
    text_exit_rect.left = frame_size[0]*unit - text_exit_rect.width
    while True:
        for event in pygame.event.get():
            #设置退出
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.pos[0] > text_start_rect.left \
                and event.pos[0] < text_start_rect.right \
                and event.pos[1] > text_start_rect.top \
                and event.pos[1] < text_start_rect.bottom:
                    return True
                elif event.pos[0] > text_exit_rect.left \
                and event.pos[0] < text_exit_rect.right \
                and event.pos[1] > text_exit_rect.top \
                and event.pos[1] < text_exit_rect.bottom:
                    pygame.quit()
                    sys.exit()
        text_start_rect = text_start_rect.move(speed_start[0], speed_start[1])
        text_exit_rect = text_exit_rect.move(speed_exit[0], speed_exit[1])
        if text_start_rect.left < 0 or text_start_rect.right > frame_size[0] * unit:
            speed_start[0] = - speed_start[0]
        if text_start_rect.top < 0 or text_start_rect.bottom > frame_size[1] * unit:
            speed_start[1] = - speed_start[1]
        if text_exit_rect.left < 0 or text_exit_rect.right > frame_size[0] * unit:
            speed_exit[0] = - speed_exit[0]
        if text_exit_rect.top < 0 or text_exit_rect.bottom > frame_size[1] * unit:
            speed_exit[1] = - speed_exit[1]
        screen.fill((255, 255, 255))
        screen.blit(text_start, text_start_rect)
        screen.blit(text_exit,text_exit_rect)
        pygame.display.update()
        clock.tick(300)


#游戏主体函数
def maingame():
    global unit
    # 游戏开始时生成蛇的头部(游戏中的头部,身体和食物均以坐标元组(x,y)表示
    head = [5 * unit, 5 * unit]
    # 使用列表来表示整条蛇,游戏开始时只有头部和两节身体
    snack = [head, [4 * unit, 5 * unit], [3 * unit, 5 * unit]]
    #用于检测头部是否触碰身体
    collision = False
    # 设置蛇默认的移动方向
    direction = RIGHT
    # 用于判断画面中是否已经存在食物,如果不存在(被吃掉)就重新生成食物
    food_exist = False
    # 用来保存食物的位置
    food_site = (0, 0)
    # 用于控制移动频率
    delay = 0
    while True:
        for event in pygame.event.get():
            #设置退出
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            #设置按钮操作监听
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    #按下上建如果当前方向不是向下,则设置方向向上,并移动一次
                    if direction != DOWN:
                        direction = UP
                        #重置delay,防止移动后立即再次移动
                        delay = 0
                        snack = move(direction, snack)
                elif event.key == pygame.K_DOWN:
                    if direction != UP:
                        direction = DOWN
                        delay = 0
                        snack = move(direction, snack)
                elif event.key == pygame.K_RIGHT:
                    if direction != LEFT:
                        direction = RIGHT
                        delay = 0
                        snack = move(direction, snack)
                elif event.key == pygame.K_LEFT:
                    if direction != RIGHT:
                        direction = LEFT
                        delay = 0
                        snack = move(direction, snack)
        #当不存在食物时,创建食物
        if not food_exist:
            food_site = gen(snack)
            food_exist = not food_exist
        #填充窗体背景为白色
        screen.fill((255, 255, 255))
        delay = (delay + 1) % 90

        #如果头部和食物坐标相同,代表食物被吃,重新生成食物,身体加一
        if snack[0][0] == food_site[0] and snack[0][1] == food_site[1]:
            food_exist = False
            #在身体的第一块设置新的身体,便于检测头部与身体的碰撞
            snack.append(snack[1])

        #画面没刷新30此执行一次移动
        if not delay%30:
            snack = move(direction, snack)
        #绘制得分,得分为snack的长度减3
        text = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
        screen.blit(text,(30,30))

        #绘制蛇
        for each in snack:
            screen.blit(image_body, (each[0], each[1]))
        #重新绘制头部
        screen.blit(image_head,(snack[0][0], snack[0][1]))
        #绘制食物
        screen.blit(image_food,(food_site[0],food_site[1]))

        #检测头部是否与身体碰撞
        for each in snack[1:]:
            if each[0] == snack[0][0] and each[1] == snack[0][1]:
                collision = True

        #如果头部碰墙,则游戏结束,绘制游戏结束画面
        if snack[0][0] < 0 or snack[0][1] < 0 \
        or snack[0][0] + unit > frame_size[0]*unit \
        or snack[0][1] + unit > frame_size[1]*unit\
        or collision:
            screen.fill((255,255,255))
            text_again = font_start.render("GameOver", True, (255, 0, 0))
            screen.blit(text_again, (450, 100))
            text_score = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
            screen.blit(text_score, (510, 200))
            text_again = font_start.render("重新开始", True, (255, 0, 0))
            screen.blit(text_again, (480, 300))
            text_exit = font_start.render("退出游戏", True, (255, 0, 0))
            screen.blit(text_exit, (480, 400))
            pygame.display.update()
            while True:
                for event in pygame.event.get():
                    # 设置退出
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        sys.exit()
                    elif event.type == pygame.MOUSEBUTTONDOWN:
                        #点击重新开始
                        if event.pos[0] > 480\
                            and event.pos[0] < 480 + text_again.get_rect().width\
                            and event.pos[1] > 300\
                            and event.pos[1] < 300 + text_again.get_rect().height:
                            return True
                        #点击退出游戏
                        elif event.pos[0] > 480\
                            and event.pos[0] < 480 + text_exit.get_rect().width\
                            and event.pos[1] > 400\
                            and event.pos[1] < 400 + text_exit.get_rect().height:
                            pygame.quit()
                            sys.exit()
        #设置刷新帧率
        clock.tick(50)
        #更新画面
        pygame.display.update()

if __name__ == '__main__':
    #控制界面显示
    Start = False
    while True:
        if Start:
            Start = maingame()
        else:
            Start = gamestart()



游戏界面
## 生成一个适合你的列表

标签:snack,text,event,exit,pygame,日记,rect,贪吃
来源: https://blog.csdn.net/qq_36947570/article/details/105667732