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

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

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

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

源码文件: https://download.csdn.net/download/qq_36947570/12348761.

详细注释源码

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()




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

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pygame模块可以用来实现很多有趣的游戏,其中包括经典的贪吃游戏。通过使用Pygame模块的绘图功能,可以实现一个具有视觉效果的贪吃游戏。 下面是一个简单的贪吃游戏的实现: ```python import pygame import random # 初始化游戏 pygame.init() # 定义游戏窗口大小 win_width = 800 win_height = 600 # 创建游戏窗口 win = pygame.display.set_mode((win_width, win_height)) # 设置游戏标题 pygame.display.set_caption("贪吃") # 定义颜色 white = (255, 255, 255) black = (0, 0, 0) red = (255, 0, 0) green = (0, 255, 0) # 设置游戏时钟 clock = pygame.time.Clock() # 定义的属性 snake_block = 10 snake_speed = 15 # 定义字体 font_style = pygame.font.SysFont(None, 50) # 定义函数,用于显示文字 def message(msg, color): message = font_style.render(msg, True, color) win.blit(message, [win_width / 6, win_height / 3]) # 定义函数,用于绘制 def draw_snake(snake_block, snake_list): for x in snake_list: pygame.draw.rect(win, green, [x[0], x[1], snake_block, snake_block]) # 定义游戏循环 def game_loop(): game_over = False game_close = False # 定义的初始位置 x1 = win_width / 2 y1 = win_height / 2 # 定义的移动方向 x1_change = 0 y1_change = 0 # 定义的初始长度 snake_List = [] Length_of_snake = 1 # 定义食物的初始位置 foodx = round(random.randrange(0, win_width - snake_block) / 10.0) * 10.0 foody = round(random.randrange(0, win_height - snake_block) / 10.0) * 10.0 # 游戏循环 while not game_over: while game_close == True: win.fill(white) message("你输了,按 Q 退出,按 C 重新开始!", red) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: game_over = True game_close = False if event.key == pygame.K_c: game_loop() for event in pygame.event.get(): if event.type == pygame.QUIT: game_over = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: x1_change = -snake_block y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = snake_block y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block x1_change = 0 elif event.key == pygame.K_DOWN: y1_change = snake_block x1_change = 0 # 判断是否超出边界 if x1 >= win_width or x1 < 0 or y1 >= win_height or y1 < 0: game_close = True # 更新的位置 x1 += x1_change y1 += y1_change # 绘制游戏背景 win.fill(white) # 绘制食物 pygame.draw.rect(win, red, [foodx, foody, snake_block, snake_block]) # 更新的长度 snake_Head = [] snake_Head.append(x1) snake_Head.append(y1) snake_List.append(snake_Head) if len(snake_List) > Length_of_snake: del snake_List[0] # 判断是否吃到食物 for x in snake_List[:-1]: if x == snake_Head: game_close = True # 绘制 draw_snake(snake_block, snake_List) # 更新游戏窗口 pygame.display.update() # 判断是否吃到食物 if x1 == foodx and y1 == foody: foodx = round(random.randrange(0, win_width - snake_block) / 10.0) * 10.0 foody = round(random.randrange(0, win_height - snake_block) / 10.0) * 10.0 Length_of_snake += 1 # 设置游戏速度 clock.tick(snake_speed) # 退出游戏 pygame.quit() quit() # 启动游戏循环 game_loop() ``` 这个程序可以实现一个基本的贪吃游戏,玩家可以使用方向键控制的移动方向,吃到食物后的长度会增加。当碰到边界或自己时,游戏结束。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值