相信对读者来说,贪吃蛇游戏已经不新鲜了,这一经典的益智游戏早已风靡世界多年。
典型的贪吃蛇游戏的主界面如图 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
至此,小游戏贪吃蛇的主要内容和关键代码介绍完毕。