贪吃蛇的玩法
用游戏把子上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴。
原理简介
相信我们绝大多数的人都玩过贪吃蛇这款游戏
今天我们就用Pygame制作这款游戏
但是首先我们得弄明白它的实现原理是什么
这是一条蛇,红色的线条就是移动的方向。
移动小蛇就是删去最后的方块,在蛇头前面添加一个方块(红叉代表删去方块)这样就达到了移动蛇的身体
所需工具
pygame
实际代码
首先我们先导入模块
import pygame, sys, random
from pygame.locals import *
然后初始化一些常量
# 屏幕大小
WINDOWWIDTH = 300
WINDOWHEIGHT = 300
FPS = 60
# 字体大小
BASICFONTSIZE = 20MAPSIZE = 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, STATEpygame.init() # 初始化pygameFPSCLOCK = 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 += 1if count > 8:# 蛇移动count = 0SnakeMove(BODYS)top = len(BODYS) -1if 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 = LEFTif event.key == K_RIGHT or event.key == K_d:if DIRECTION != LEFT:DIRECTION = RIGHTif event.key == K_UP or event.key == K_w:if DIRECTION != DOWN:DIRECTION = UPif 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)-1if 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 0draw.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, STATEpygame.init()FPSCLOCK = pygame.time.Clock()DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH ,WINDOWHEIGHT))pygame.display.set_caption('贪吃蛇')BASICFONT = pygame.font.Font('freesansbold.ttf', BASICFONTSIZE)DIRECTION = RIGHTSTATE = 1foodx, foody = random.randint(0, MAPSIZE), random.randint(0, MAPSIZE)count = 0while STATE:DISPLAYSURF.fill(WHITE)STATE = DrawSnake(BODYS, foodx, foody)count += 1if count > 8:count = 0SnakeMove(BODYS)top = len(BODYS) -1if BODYS[top][1] > MAPSIZE or BODYS[top][0] > MAPSIZE or BODYS[top][1] < 0 or BODYS[top][0] < 0:STATE = 0for 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 = LEFTif event.key == K_RIGHT or event.key == K_d:if DIRECTION != LEFT:DIRECTION = RIGHTif event.key == K_UP or event.key == K_w:if DIRECTION != DOWN:DIRECTION = UPif event.key == K_DOWN or event.key == K_s:if DIRECTION != UP:DIRECTION = DOWNif 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)-1if 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 0draw.append(body)pygame.draw.circle(DISPLAYSURF, RED, (foodx*20+10, foody*20+10),10,0)return 1def 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()
我第一次写写的不太好