贪吃蛇的玩法
用游戏把子上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴。
原理简介
相信我们绝大多数的人都玩过贪吃蛇这款游戏
今天我们就用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()
我第一次写写的不太好