贪吃蛇
贪吃蛇是一款非常经典的游戏,随机生成红色方块,通过移动蛇头吃掉红色方块
1. 游戏初始界面
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 import pygame
from pygame.locals import *
import sys
# 屏幕刷新率(在这里相当于贪吃蛇的速度)
FPS = 5
# 屏幕宽度
WINDOWWIDTH = 640
# 屏幕高度
WINDOWHEIGHT = 480
# 小方格的大小
CELLSIZE = 20
# 定义常用颜色
WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
RED = ( 255 , 0 , 0 )
GREEN = ( 0 , 255 , 0 )
DARKGREEN = ( 0 , 155 , 0 )
DARKGRAY = ( 40 , 40 , 40 )
BGCOLOR = BLACK
def main ():
# 定义全局变量
global FPSCLOCK , DISPLAYSURF , BASICFONT
# 初始化pygame
pygame . init ()
# 获得pygame时钟
FPSCLOCK = pygame . time . Clock ()
# 设置屏幕宽高
DISPLAYSURF = pygame . display . set_mode (( WINDOWWIDTH , WINDOWHEIGHT ))
# 设置基本字体
BASICFONT = pygame . font . Font ( 'resources/ARBERKLEY.ttf' , 18 )
# 设置窗口的标题
pygame . display . set_caption ( 'Snake' )
# 显示游戏开始画面
showStartScreen ()
if __name__ == '__main__' :
main ()
main方法中主要展示了游戏窗口并设置标题
showStartScreen方法如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 # 退出游戏
def terminate ():
pygame . quit ()
sys . exit ()
# 检测按键事件
def checkForKeyPress ():
if len ( pygame . event . get ( QUIT )) > 0 :
terminate ()
keyUpEvents = pygame . event . get ( KEYUP )
if len ( keyUpEvents ) == 0 :
return None
if keyUpEvents [ 0 ] . key == K_ESCAPE :
terminate ()
return keyUpEvents [ 0 ] . key
# 提示按键消息
def drawPressKeyMsg ():
pressKeySurf = BASICFONT . render ( 'Press a key to play.' , True , RED )
pressKeyRect = pressKeySurf . get_rect ()
pressKeyRect . topleft = ( WINDOWWIDTH - 200 , WINDOWHEIGHT - 30 )
DISPLAYSURF . blit ( pressKeySurf , pressKeyRect )
# 显示游戏开始画面
def showStartScreen ():
DISPLAYSURF . fill ( BGCOLOR )
titleFont = pygame . font . Font ( 'resources/ARBERKLEY.ttf' , 100 )
titleSurf = titleFont . render ( 'Snake!' , True , GREEN )
titleRect = titleSurf . get_rect ()
titleRect . center = ( WINDOWWIDTH / 2 , WINDOWHEIGHT / 2 )
DISPLAYSURF . blit ( titleSurf , titleRect )
# 下方提示文字
drawPressKeyMsg ()
pygame . display . update ()
# 检查按键
while True :
if checkForKeyPress ():
pygame . event . get ()
return
showStartScreen:
填充背景颜色
显示Snake字体
drawPressKeyMsg:
用来显示下方提示文字
checkForKeyPress:
检查是否按下了键盘,如果按下ESC
就停止游戏,按下其它键盘就进入游戏界面
2. 游戏引擎
def main ():
...
while True :
# 这里一直循环于游戏运行时和显示游戏结束画面之间,运行游戏里有一个循环,显示游戏结束画面也有一个循环,两个循环都有相应的return,这样就可以达到切换这两个模块的效果
# 运行游戏
runGame ()
3. 初始化游戏网格
随机一个起点,建立长度三格的贪吃蛇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 # 游戏运行时
def runGame ():
# 游戏主循环
while True :
# 事件处理
for event in pygame . event . get ():
# 退出事件
if event . type == QUIT :
terminate ()
# 绘制背景
DISPLAYSURF . fill ( BGCOLOR )
# 绘制所有的方格
drawGrid ()
# 更新屏幕
pygame . display . update ()
# 设置帧率
FPSCLOCK . tick ( FPS )
4. 初始化贪吃蛇
1、定义drawWorm
方法根据网格列表来绘制贪吃蛇
# 根据wormCoords列表绘制贪吃蛇
def drawWorm ( wormCoords ):
for coord in wormCoords :
x = coord [ 'x' ] * CELLSIZE
y = coord [ 'y' ] * CELLSIZE
wormSegmentRect = pygame . Rect ( x , y , CELLSIZE , CELLSIZE )
pygame . draw . rect ( DISPLAYSURF , DARKGREEN , wormSegmentRect )
wormInnerSegmentRect = pygame . Rect ( x + 4 , y + 4 , CELLSIZE - 8 , CELLSIZE - 8 )
pygame . draw . rect ( DISPLAYSURF , GREEN , wormInnerSegmentRect )
2、在runGame
方法中展示贪吃蛇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 # 游戏运行时
def runGame ():
# 随机初始化设置一个点作为贪吃蛇的起点
startx = random . randint ( 5 , CELLWIDTH - 6 )
starty = random . randint ( 5 , CELLHEIGHT - 6 )
# 以这个点为起点,建立一个长度为3格的贪吃蛇(列表)
wormCoords = [{ 'x' : startx , 'y' : starty },
{ 'x' : startx - 1 , 'y' : starty },
{ 'x' : startx - 2 , 'y' : starty }]
direction = RIGHT # 初始化一个运动的方向
# 游戏主循环
while True :
...
# 绘制贪吃蛇
drawWorm ( wormCoords )
...
贪吃蛇展示:
5. 展示苹果
1、定义随机生成红色方格方法getRandomLocation
# 随机生成一个苹果的坐标位置
def getRandomLocation ():
return { 'x' : random . randint ( 0 , CELLWIDTH - 1 ), 'y' : random . randint ( 0 , CELLHEIGHT - 1 )}
2、制红色方格
def runGame ():
while True :
...
# 绘制苹果
drawApple ( apple )
红色方格展示:
6. 贪吃蛇自动移动
贪吃蛇的移动其实就是移除最后一个格子,前面再添加一个格子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 def runGame ():
...
# 游戏主循环
while True :
# 事件处理
for event in pygame . event . get ():
...
# 按键事件
elif event . type == KEYDOWN :
#如果按下的是左键或a键,且当前的方向不是向右,就改变方向,以此类推
if ( event . key == K_LEFT or event . key == K_a ) and direction != RIGHT :
direction = LEFT
elif ( event . key == K_RIGHT or event . key == K_d ) and direction != LEFT :
direction = RIGHT
elif ( event . key == K_UP or event . key == K_w ) and direction != DOWN :
direction = UP
elif ( event . key == K_DOWN or event . key == K_s ) and direction != UP :
direction = DOWN
elif event . key == K_ESCAPE :
terminate ()
# 移除蛇的最后一个尾巴格
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 )
7. 贪吃蛇吃苹果
贪吃蛇吃到苹果其实就是蛇头的网格坐标和苹果的网格坐标重合
如果吃到苹果,则蛇增加一个格子(不用再删除尾部格子即可)
随机再生成一个苹果
1
2
3
4
5
6
7
8
9
10
11
12
13
14 def runGame ():
...
# 游戏主循环
while True :
...
# 检查贪吃蛇是否吃到苹果,若没吃到,则删除尾端,蛇身前进一格
if wormCoords [ HEAD ][ 'x' ] == apple [ 'x' ] and wormCoords [ HEAD ][ 'y' ] == apple [ 'y' ]:
# 不移除蛇的最后一个尾巴格
# 重新随机生成一个苹果
apple = getRandomLocation ()
else :
# 移除蛇的最后一个尾巴格
del wormCoords [ - 1 ]
...
随机生成新的苹果方法getRandomLocation
如下:
# 随机生成一个苹果的坐标位置
def getRandomLocation ():
return { 'x' : random . randint ( 0 , CELLWIDTH - 1 ), 'y' : random . randint ( 0 , CELLHEIGHT - 1 )}
8. 分数显示
1、定义绘制分数的drawScore
方法
# 显示分数
def drawScore ( score ):
scoreSurf = BASICFONT . render ( 'Score: %s ' % ( score ), True , WHITE )
scoreRect = scoreSurf . get_rect ()
scoreRect . topleft = ( WINDOWWIDTH - 120 , 10 )
DISPLAYSURF . blit ( scoreSurf , scoreRect )
2、在runGame
中绘制分数
def runGame ():
while True :
...
# 绘制分数(分数为贪吃蛇列表当前的长度-3)
drawScore ( len ( wormCoords ) - 3 )
...
分数展示:
9. 贪吃蛇碰到边界处理
碰撞到边界,只需要退出当前绘制游戏界面的循环,进入游戏结束处理即可
def runGame ():
while True :
...
# 检查贪吃蛇是否撞到撞到边界,即检查蛇头的坐标
if wormCoords [ HEAD ][ 'x' ] == - 1 or wormCoords [ HEAD ][ 'x' ] == CELLWIDTH or wormCoords [ HEAD ][ 'y' ] == - 1 or wormCoords [ HEAD ][ 'y' ] == CELLHEIGHT :
# game over
return
...
10. 贪吃蛇撞到自己的处理
判断贪吃蛇是否碰到自己,只需要看蛇头的坐标是否和蛇身的坐标是否重叠即可
def runGame ():
while True :
...
# 检查贪吃蛇是否撞到自己,即检查蛇头的坐标是否等于蛇身的坐标
for wormBody in wormCoords [ 1 :]:
if wormBody [ 'x' ] == wormCoords [ HEAD ][ 'x' ] and wormBody [ 'y' ] == wormCoords [ HEAD ][ 'y' ]:
# game over
return
...
11. 游戏结束处理
1、定义显示游戏结束的方法showGameOverScreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 # 显示游戏结束画面
def showGameOverScreen ():
gameOverFont = pygame . font . Font ( 'resources/ARBERKLEY.ttf' , 50 )
gameSurf = gameOverFont . render ( 'Game' , True , WHITE )
overSurf = gameOverFont . render ( 'Over' , True , WHITE )
gameRect = gameSurf . get_rect ()
overRect = overSurf . get_rect ()
gameRect . midtop = ( WINDOWWIDTH / 2 , WINDOWHEIGHT / 2 - gameRect . height - 10 )
overRect . midtop = ( WINDOWWIDTH / 2 , WINDOWHEIGHT / 2 )
DISPLAYSURF . blit ( gameSurf , gameRect )
DISPLAYSURF . blit ( overSurf , overRect )
drawPressKeyMsg ()
pygame . display . update ()
pygame . time . wait ( 500 )
checkForKeyPress ()
while True :
if checkForKeyPress ():
pygame . event . get ()
return
展示游戏结束的画面,并监听事件
2、在main
方法中执行游戏结束方法
def main ():
...
while True :
# 运行游戏
runGame ()
# 显示游戏结束画面
showGameOverScreen ()