相信对读者来说,贪吃蛇游戏已经不新鲜了,这一经典的益智游戏早已风靡世界多年。
典型的贪吃蛇游戏的主界面如图 1 所示。
其游戏规则是:玩家使用上下左右键控制绿色的“蛇”在窗口中游走并吃掉(触碰)红色的“苹果”来得分,每吃一个“苹果”,“蛇”也将变长一些。如果“蛇头”碰到了窗口的四壁,或是与自身相撞,游戏结束。整个界面由若干方格构成,“蛇”游走的过程实际上是在不同的方格中连续绘制和擦除“蛇”的图形的过程。
根据游戏规则整理出的游戏流程如图 2 所示。
根据流程图,与 2048 小游戏类似,贪吃蛇游戏程序大致也可分为三个部分:
其中第三部分可以继续细分为以下三个部分:
为了游戏界面效果美观,同样使用了 pygame 模块。首先来看程序初始化,这里主要完成以下工作:导入所需模块,初始化窗口界面,初始化各种组件和变量。代码如下:
#“蛇”移动的速度,数值越大速度越快
Snakespeed = 10
#窗口宽度和高度
Window_Width = 800
Window_Height = 500
#每个格子的宽度和高度
Cell_Size = 20
assert Window_Width % Cell_Size == 0, "窗口宽度必须是格子宽度的整数倍"
assert Window_Height % Cell_Size ==0, "窗口高度必须是格子高度的整数倍"
Cell W = int(Window Width / Cell_Size) # Cell Width
Cell_H = int(Window_Height / Cell_Size) # Celle Height
#定义游戏用到的颜色值
White = (255, 255, 255)
Black = (0, 0, 0)
Red = (255, 0, 0)
Green = (0, 255, 0)
DARKGreen = (0, 155, 0)
DARKGRAY = (40, 40, 40)
YELLOW = (255, 255, 0)
Red_DARK = (150, 0, 0)
BLUE = (0, 0, 255)
BLUE_DARK = (0, 0, 150)
BGCOLOR = Black
#定义游戏用到的控制键
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
HEAD = 0
#定义游戏字体
FONTNAME = "SimHei"
判断用户输入是通过执行 showStartScreen( ) 函数实现的,其代码如下:
def showStartScreen():
while True:
drawPressKeyMsg()
if checkForKeyPress ():
pygame.event.get()
return
pygame.display.update()
def drawPressKeyMsg():
pressKey Surf = BASICFONT.render('按任意键开始游戏', True, White)
pressKeyRect = pressKeySurf.get_rect()
pressKeyRect.topleft = (Window_Width - 200, Window_Height - 30)
DISPLAYSURF.blit(pressKeySurf, pressKeyRect)
可见,贪吃蛇也是通过无限循环实现的,依然使用了事件机制获取用户输入,当用户按下任意键时跳出循环,向下执行。
游戏主循环是通过 runGame( ) 函数实现的,其代码如下:
def runGame():
#随机选取“蛇”的起始位置
startx = random.randint(5, Cell_W - 6)
starty = random.randint(5, Cell_H - 6)
wormCoords = [{'x': startx, 'y': starty},
{'x': startx - 1, 'y' : starty},
{'x' : startx - 2, 'y' : starty}]
#设置“蛇”的初始运动方向为向右
direction = RIGHT
#随机选取一个位置生成“苹果”
apple = getRandomLocation()
#主循环
while True:
for event in pygame.event.get(): # event handling loop
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if(event.key == K_LEFT) and direction != RIGHT:
direction = LEFT
elif(event.key == K_RIGHT) and direction != LEFT:
direction = RIGHT
elif(event.key == K_UP) and direction != DOWN:
direction = UP
elif (event.key == K_DOWN) and direction != UP:
direction = DOWN
elif event.key == K_ESCAPE:
terminate()
#检测“蛇”是否撞到自身或窗口边缘
if wormCoords[HEAD] ['x'] == -1 or wormCoords [HEAD] ['x'] == Cell_W or wormCoords[HEAD] ['y'] == -1 or wormCoords[HEAD] ['y'] == Cell_H:
return # game over
for wormBody in wormCoords[1:]:
if wormBody['x'] == wormCoords[HEAD] ['x'] and wormBody['y'] ==wormCoords[HEAD] ['y']:
return # game over
#检测“蛇”是否吃到“苹果”
if wormCoords[HEAD] ['x'] == apple['x'] and wormCoords[HEAD] ['y'] ==apple['y']:
apple = getRandomLocation()
else :
del wormCoords[-1]
#沿着“蛇”运动的方向增加其长度
if direction == UP:
newHead = {'x': wormCoords[HEAD] ['x'], 'y': wormCoords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {'x': wormCoords[HEAD] ['x'], 'y': wormCoords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {'x': wormCoords [HEAD] ['x'] - 1, 'y': wormCoords[HEAD]['y'] }
elif direction == RIGHT:
newHead = {'x': wormCoords [HEAD] ['x'] + 1, 'y': wormCoords [HEAD]['y'] }
wormCoords.insert(0, newHead)
#绘制主界面和方格、“蛇”、“苹果”、分数等游戏元素
DISPLAYSURF.fill(BGCOLOR)
drawGrid()
drawWorm(wormCoords)
drawApple(apple)
drawScore(len(wormCoords) - 3)
pygame.display.update()
SnakespeedCLOCK.tick(Snakespeed)
当“蛇”撞到自身或窗口边缘时,游戏结束,此时将执行 showGameOverScreen( ) 函数,其代码如下:
def showGameOverScreen():
gameOverFont = pygame.font.SysFont(FONTNAME, 100)
gameSurf = gameOverFont.render('游戏', True, White)
overSurf = gameOverFont.render('结束', True, White)
gameRect = gameSurf.get_rect()
overRect = overSurf.get_rect()
gameRect.midtop = (Window_Width / 2, 80)
overRect.midtop = (Window_Width / 2, gameRect.height + 50 + 25)
DISPLAYSURF.blit(gameSurf, gameRect)
DISPLAYSURF.blit (overSur, overRect)
drawPressKeyMsg()
pygame.display.update()
pygame.time.wait(500)
checkForKeyPress () # clear out any key presses in the event queue
while True:
if checkForKeyPress():
pygame.event.get() # clear event queue
return
至此,小游戏贪吃蛇的主要内容和关键代码介绍完毕。