Pygame Zero之贪吃蛇(四)

本篇来给贪吃蛇增加游戏规则判定并加入食物和分数,制作一个完整的贪吃蛇游戏。

游戏规则判定

在游戏中,出现两种情况则视为游戏失败:

  • 小蛇撞墙,即蛇头碰到屏幕边界
  • 小蛇吃自己,即蛇头碰到身体

首先定义一个布尔类型的变量,用来记录游戏是否失败。稍后通过条件判断来修改变量的值。

1
isLose = False

小蛇撞墙

首先判断第一种情况,当小蛇撞墙时,游戏失败。

由于小蛇一直是蛇头走在最前面,所以在update中只需要判断蛇头的坐标是否超过窗口边界坐标。

1
2
if newSnakeHead.y < 0 or newSnakeHead.y > HEIGHT or newSnakeHead.x < 0 or newSnakeHead.x > WIDTH:
isLose = True

draw()函数中,添加游戏失败的显示信息:

1
2
3
4
5
6
7
def draw():
screen.clear()
for snakebody in Snake:
snakebody.draw()
# 显示游戏失败信息
if isLose:
screen.draw.text("Game over!", (180, HEIGHT / 2 - 100), fontsize=100, color='skyblue')

小蛇吃自己

当小蛇吃到自己时,同样游戏结束。遍历每一个身体方块,当蛇头和任一身体坐标重合时,那就是吃到蛇肉啦。

1
2
3
4
for snakebody in Snake:
if newSnakeHead.x == snakebody.x and newSnakeHead.y == snakebody.y:
isLose = True
break

食物的随机出现

食物初始状态

首先需要将食物的图片放在images文件夹中。

1
2
3
4
5
6
7
8
9
10
import random

# 初始位置随机
cookie = Actor('cookie')
cookie.x = random.randint(10,30)*TILE_SIZE
cookie.y = random.randint(10,30)*TILE_SIZE


def draw():
cookie.draw()

吃到食物增加长度

如果在一次移动中,小蛇没有吃到食物,那么就需要删除旧的蛇尾。如果小蛇吃到了食物,那么就不需要删除旧蛇尾了,直接在食物的位置添加一个新的蛇头即可。

怎样算吃到食物?newSnakeHead.x == cookie.x and newSnakeHead.y == cookie.y

在之前的update()函数中修改:

1
2
3
4
5
6
7
8
def update():
# 小蛇吃到食物后无需删除蛇尾,将食物位置重新随机
if newSnakeHead.x == cookie.x and newSnakeHead.y == cookie.y:
cookie.x = random.randint(5, 35) * TILE_SIZE
cookie.y = random.randint(5, 25) * TILE_SIZE
else:
del Snake[len(Snake) - 1]
Snake.insert(0, newSnakeHead)

到目前为止,整体游戏效果已经比较完整!

显示得分

接下来的功能是一个优化,就是分数的显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
score = 0


# 在窗口左上角显示分数
def draw():
screen.draw.text("Score:" + str(score), (20, 20), fontsize=25, color='white')


# 吃到食物加1分
def update():
global score
if newSnakeHead.x == cookie.x and newSnakeHead.y == cookie.y:
score += 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import random

import pgzrun

TILE_SIZE = 20
WIDTH = 40 * TILE_SIZE
HEIGHT = 30 * TILE_SIZE
isLose = False

snakehead = Actor('snake1')
snakehead.x = WIDTH / 2
snakehead.y = HEIGHT / 2

cookie = Actor('cookie')
cookie.x = random.randint(10, 30) * TILE_SIZE
cookie.y = random.randint(10, 30) * TILE_SIZE

Snake = [snakehead]

for i in range(4):
snakebody = Actor('snake1')
snakebody.x = Snake[i].x - TILE_SIZE
snakebody.y = Snake[i].y
Snake.append(snakebody)

direction = 'right'
score = 0


def draw():
screen.clear()
cookie.draw()
for snakebody in Snake:
snakebody.draw()
if isLose:
screen.draw.text("Game over!", (180, HEIGHT / 2 - 100), fontsize=100,
color='skyblue')
screen.draw.text("Score: " + str(score), (20, 20), fontsize=25,
color='white')


def update():
global direction, isLose, score
if keyboard.left:
direction = 'left'
if keyboard.right:
direction = 'right'
if keyboard.up:
direction = 'up'
if keyboard.down:
direction = 'down'
newSnakeHead = Actor('snake1') # 创建新蛇头
if direction == 'up':
newSnakeHead.x = Snake[0].x
newSnakeHead.y = Snake[0].y - TILE_SIZE
if direction == 'down':
newSnakeHead.x = Snake[0].x
newSnakeHead.y = Snake[0].y + TILE_SIZE
if direction == 'left':
newSnakeHead.x = Snake[0].x - TILE_SIZE
newSnakeHead.y = Snake[0].y
if direction == 'right':
newSnakeHead.x = Snake[0].x + TILE_SIZE
newSnakeHead.y = Snake[0].y

if newSnakeHead.y < 0 or newSnakeHead.y > HEIGHT or newSnakeHead.x < 0 or newSnakeHead.x > WIDTH:
isLose = True
for body in Snake:
if newSnakeHead.x == body.x and newSnakeHead.y == body.y:
isLose = True
break

if newSnakeHead.x == cookie.x and newSnakeHead.y == cookie.y:
score += 1
cookie.x = random.randint(5, 35) * TILE_SIZE
cookie.y = random.randint(5, 25) * TILE_SIZE
else:
del Snake[len(Snake) - 1]
Snake.insert(0, newSnakeHead)


pgzrun.go()