详细Pygame制作贪吃蛇

贪吃蛇的玩法

用游戏把子上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴。

原理简介

相信我们绝大多数的人都玩过贪吃蛇这款游戏
今天我们就用Pygame制作这款游戏
但是首先我们得弄明白它的实现原理是什么

这是一条蛇,红色的线条就是移动的方向。
在这里插入图片描述
移动小蛇就是删去最后的方块,在蛇头前面添加一个方块(红叉代表删去方块)这样就达到了移动蛇的身体
在这里插入图片描述

所需工具

pygame

实际代码

首先我们先导入模块

import pygame, sys, random
from pygame.locals import *

然后初始化一些常量

# 屏幕大小
WINDOWWIDTH = 300
WINDOWHEIGHT = 300
FPS = 60
# 字体大小
BASICFONTSIZE = 20

MAPSIZE = 14
#                 R    G    B
BLACK =         (  0,   0,   0)
WHITE =         (255, 255, 255)
BRIGHTBLUE =    (  0,  50, 255)
DARKTURQUOISE = (  3,  54,  73)
GREEN =         (  0, 255,   0)
RED =           (255, 0  ,   0)
DARKGREEN =     (10 , 255, 100)
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
# 蛇的身体
BODYS = [[2,2],[2,3],[3,3]] 

接下我们用Pygame来创建一个窗口

def main():
    global FPSCLOCK, DISPLAYSURF, BASICFONT, DIRECTION, STATE

    pygame.init() # 初始化pygame
    FPSCLOCK = pygame.time.Clock()
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH ,WINDOWHEIGHT))
    pygame.display.set_caption('贪吃蛇')
    BASICFONT = pygame.font.Font('freesansbold.ttf', BASICFONTSIZE)
    DIRECTION = RIGHT # 蛇的方向
    STATE = 1 # 游戏状态(1=活,0=死)
    
    foodx, foody = random.randint(0, MAPSIZE), random.randint(0, MAPSIZE)# 食物的坐标
    count = 0 # 用来计算蛇什么时候移动

然后就可以进入我们的游戏循环了Drawsnake函数和SnakeMove我将会在后边讲解。当我们的count变量大于8时也就是说蛇该移动了,为什么要有count?你去掉count试试就知道了。top记录的是蛇头的位置,然后用来检测蛇头是否碰撞墙壁。

    while STATE:
        DISPLAYSURF.fill(WHITE) # 背景填充颜色
        STATE = DrawSnake(BODYS, foodx, foody) # 这个绘制蛇身会返回一个蛇有没有死
        count += 1
        if count > 8:
      		# 蛇移动
            count = 0
            SnakeMove(BODYS)
            top = len(BODYS) -1
            if BODYS[top][1] > MAPSIZE or BODYS[top][0] > MAPSIZE or BODYS[top][1] < 0 or BODYS[top][0] < 0:#判定是否撞墙
                STATE = 0

接下来我们检测用户的输入。如果用户松开按钮的话就检测AWSD或者是↑↓←→,但是必须得判断是否回头,程序不允许玩家回头。在这里插入图片描述

        for event in pygame.event.get():
            if event.type == QUIT: # 点击了退出按钮
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                if event.key == K_LEFT or event.key == K_a:
                    if  DIRECTION != RIGHT:
                        DIRECTION = LEFT
                if event.key == K_RIGHT or event.key == K_d:
                    if  DIRECTION != LEFT:
                        DIRECTION = RIGHT
                if event.key == K_UP or event.key == K_w:
                    if  DIRECTION != DOWN:
                        DIRECTION = UP
                if event.key == K_DOWN or event.key == K_s:
                    if  DIRECTION != UP:
                        DIRECTION = DOWN

为了让用户知道自己的分数,就在左上角打印出用户的分数。这个分数按照蛇的身体长度来定。这里用到了一个函数makeText,makeText并不是pygame的函数,是我自己写的我将会在后面介绍

        textSurf, textRect = makeText('scores:'+str(len(BODYS)-1), BRIGHTBLUE, 10, 10)
        DISPLAYSURF.blit(textSurf, textRect)
        
        pygame.display.update() 
        FPSCLOCK.tick(FPS)

然后若玩家死掉了要提示一下玩家,蛇死了。所以我们就在屏幕上打印一个"You Die",但是此时还不能终止程序,因为打印了"You die"还需检测用户的退出。

    while 1:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

在这里插入图片描述

好了,现在我们来介绍前面所用到的所有函数,SnakeMove也就是执行蛇的运动。
一开始先删除蛇的尾巴,然后再在蛇头添加一个方块

def SnakeMove(bodys):
    del bodys[0] # 删除尾巴
    top = len(bodys)-1
    if DIRECTION == RIGHT:
        bodys.append([bodys[top][0]+1,bodys[top][1]])
    elif DIRECTION == LEFT:
        bodys.append([bodys[top][0]-1,bodys[top][1]])
    elif DIRECTION == DOWN:
        bodys.append([bodys[top][0],bodys[top][1]+1])
    elif DIRECTION == UP:
        bodys.append([bodys[top][0],bodys[top][1]-1])

这个是绘制蛇,比较好理解。但是我把判断蛇吃掉自己的判断也加进去了。
列表draw是已经绘制过了的方块,最后绘制circle绘制的是食物。

def DrawSnake(bodys,foodx,foody):
    draw = []
    for body in bodys:
        if body == bodys[len(bodys)-1]:
            pygame.draw.rect(DISPLAYSURF, GREEN, (body[0]*20, body[1]*20, 20, 20))
        else:
            pygame.draw.rect(DISPLAYSURF, DARKGREEN, (body[0]*20, body[1]*20, 20, 20))
        if body in draw:
            return 0
        draw.append(body)
    pygame.draw.circle(DISPLAYSURF, RED, (foodx*20+10, foody*20+10),10,0)
    return 1

好了,还有最后一个函数没有讲解,就是maketext的这个函数。这个函数相对于其他的函数比较好理解。

def makeText(text, color, top, left):
    textSurf = BASICFONT.render(text, True, color)
    textRect = textSurf.get_rect()
    textRect.topleft = (top, left)
    return (textSurf, textRect)
if __name__ == '__main__':
    main()

好了贪吃蛇制作完成了。这是贪吃蛇的全代码

import pygame, sys, random
from pygame.locals import *

WINDOWWIDTH = 300
WINDOWHEIGHT = 300
FPS = 60
BASICFONTSIZE = 20
MAPSIZE = 14
#                 R    G    B
BLACK =         (  0,   0,   0)
WHITE =         (255, 255, 255)
BRIGHTBLUE =    (  0,  50, 255)
DARKTURQUOISE = (  3,  54,  73)
GREEN =         (  0, 255,   0)
RED =           (255, 0  ,   0)
DARKGREEN =     (10 , 255, 100)
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'

BODYS = [[2,2],[2,3],[3,3]]
def main():
    global FPSCLOCK, DISPLAYSURF, BASICFONT, DIRECTION, STATE

    pygame.init()
    FPSCLOCK = pygame.time.Clock()
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH ,WINDOWHEIGHT))
    pygame.display.set_caption('贪吃蛇')
    BASICFONT = pygame.font.Font('freesansbold.ttf', BASICFONTSIZE)
    DIRECTION = RIGHT
    STATE = 1
    
    foodx, foody = random.randint(0, MAPSIZE), random.randint(0, MAPSIZE)
    count = 0
    
    while STATE:
        DISPLAYSURF.fill(WHITE)
        STATE = DrawSnake(BODYS, foodx, foody)
        count += 1
        if count > 8:
            count = 0
            SnakeMove(BODYS)
            top = len(BODYS) -1
            if BODYS[top][1] > MAPSIZE or BODYS[top][0] > MAPSIZE or BODYS[top][1] < 0 or BODYS[top][0] < 0:
                STATE = 0

    
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                if event.key == K_LEFT or event.key == K_a:
                    if  DIRECTION != RIGHT:
                        DIRECTION = LEFT
                if event.key == K_RIGHT or event.key == K_d:
                    if  DIRECTION != LEFT:
                        DIRECTION = RIGHT
                if event.key == K_UP or event.key == K_w:
                    if  DIRECTION != DOWN:
                        DIRECTION = UP
                if event.key == K_DOWN or event.key == K_s:
                    if  DIRECTION != UP:
                        DIRECTION = DOWN
                if event.key == K_f:
                    BODYS.insert(0,[-1,-1])
        if [foodx, foody] in BODYS:
            foodx, foody = random.randint(0, MAPSIZE), random.randint(0, MAPSIZE)
            BODYS.insert(0,[-1,-1])
            
        textSurf, textRect = makeText('scores:'+str(len(BODYS)-1), BRIGHTBLUE, 10, 10)
        DISPLAYSURF.blit(textSurf, textRect)
        
        pygame.display.update()
        FPSCLOCK.tick(FPS)
        
    textSurf, textRect = makeText('You Die', BLACK, 115, 140)
    DISPLAYSURF.blit(textSurf, textRect)
    pygame.display.update()
    
    while 1:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

 
def SnakeMove(bodys):
    del bodys[0]
    top = len(bodys)-1
    if DIRECTION == RIGHT:
        bodys.append([bodys[top][0]+1,bodys[top][1]])
    elif DIRECTION == LEFT:
        bodys.append([bodys[top][0]-1,bodys[top][1]])
    elif DIRECTION == DOWN:
        bodys.append([bodys[top][0],bodys[top][1]+1])
    elif DIRECTION == UP:
        bodys.append([bodys[top][0],bodys[top][1]-1])
    
def DrawSnake(bodys,foodx,foody):
    draw = []
    for body in bodys:
        if body == bodys[len(bodys)-1]:
            pygame.draw.rect(DISPLAYSURF, GREEN, (body[0]*20, body[1]*20, 20, 20))
        else:
            pygame.draw.rect(DISPLAYSURF, DARKGREEN, (body[0]*20, body[1]*20, 20, 20))
        if body in draw:
            return 0
        draw.append(body)
    pygame.draw.circle(DISPLAYSURF, RED, (foodx*20+10, foody*20+10),10,0)
    return 1
    
def makeText(text, color, top, left):
    textSurf = BASICFONT.render(text, True, color)
    textRect = textSurf.get_rect()
    textRect.topleft = (top, left)
    return (textSurf, textRect)

if __name__ == '__main__':
    main()

我第一次写写的不太好

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四十岁学做码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值