文章目录
基本抽向和常量控制逻辑绘图初始化主循环
基本抽向和常量
贪吃蛇的逻辑很简单,就是一个连续方块组成的蛇,这条蛇可以向前走,也可以向两侧转弯。如果蛇的前面有一个食物,那么蛇吃掉食物后,身体会变长。
所以,贪吃蛇可以用一组
(
x
,
y
)
(x,y)
(x,y)坐标表示,每一个坐标都是一个方块,所有方块连在一起就是蛇的身体,同理,食物可用单个的
(
x
,
y
)
(x,y)
(x,y)表示。
在初始化过程中,
(
x
,
y
)
(x,y)
(x,y)虽然是随机生成,但需要有一个范围,最起码不能超过游戏窗口的边界。为此,可将游戏窗口的尺寸设为常量,同时需要设置方块的尺寸,并通过方块和窗口尺寸的关系,得到初始化的坐标范围。
import random
import pygame.font
# 游戏窗口设置
WIDTH, HEIGHT = 800, 500
SIZE = 10
WBOX, HBOX = WIDTH // SIZE, HEIGHT // SIZE
# 定义颜色
BLACK = (0, 51, 0) # 深绿色
GREEN = (0, 255, 0) # 亮绿色
RED = (255,0,0) # 红色
# 初始化位置
newBox = lambda: (random.randrange(1, WBOX) * SIZE,
random.randrange(1, HBOX) * SIZE)
控制逻辑
在未经交互的情况下,贪吃蛇每次向前走一步,所谓一步,可以理解为贪吃蛇最小方块单元的尺寸。由于贪吃蛇的前进方向不同,故而这恶脚步所对应的坐标变化
(
d
x
,
d
y
)
(dx,dy)
(dx,dy)是不同的。在平面上,总共有四分方向,从而对应四种脚步。而调整贪吃蛇前进方向,则可通过上下左右这几个方向键来实现。最终代码如下
# 按键对应的蛇的脚步
keyDct = {
pygame.K_UP : (0,-SIZE), pygame.K_DOWN: (0,SIZE),
pygame.K_LEFT: (-SIZE,0), pygame.K_RIGHT: (SIZE,0)
}
def updateStep(step, key):
nextStep = keyDct[key]
flag = nextStep[0]+step[0] or nextStep[1]+step[1]
return nextStep if flag else step
其中,keyDct是按键和脚步的对应关系,后者则根据按键来更新贪吃蛇的前进方向。此中需要做一个判断,即按键方向和当前方向是否相反,如果贪吃蛇正在向上走,那么没法控制它向下走。
绘图
绘图时需要一个绘图窗口,剩下的就几乎没有需要注意的了,贪吃蛇和食物的绘图逻辑如下。
def drawSnake(screen, snake, food, font):
for x,y in snake:
pygame.draw.rect(screen, GREEN, pygame.Rect(x, y, SIZE, SIZE))
pygame.draw.rect(screen, RED, pygame.Rect(food[0], food[1], SIZE, SIZE))
# 显示得分
text = font.render(f"蛇身长度: {len(snake)}", True, RED)
screen.blit(text, (10, 10))
除此之外,还需要绘制游戏结束时的窗口,主要就是显示一些文字。
def drawGamerOver(screen, font):
w, h = font.size('GAME OVER')
msg = font.render('GAME OVER', True, RED)
screen.blit(msg, ((WIDTH - w) // 2, (HEIGHT - h) // 2 - 40))
w, h = font.size('点击任意位置,再来一局')
msg = font.render('点击任意位置,再来一局', True, RED)
screen.blit(msg, ((WIDTH - w) // 2, (HEIGHT - h) // 2 + 40))
初始化
游戏只需要初始化三个东西,即食物位置、蛇的位置以及蛇的前进方向,故而封装一个init()函数,返回脚步、食物、蛇头以及蛇。
# 随机选择蛇的脚步
def init():
step = random.choice(list(keyDct.values()))
food, head = newBox(), newBox()
return step, food, head, [head]
# 初始化pygame
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")
font = pygame.font.Font(r"./SimHei.ttf", 30)
step, food, head, snake = init()
running, gameOver = True, False
主循环
我们需要设置两个变量来调控循环,一个是是否继续游戏,另一个是游戏是否失败。二者分别用running和gameOver表示。
当游戏失败时,显示游戏失败的说明,同时,若按键盘怕或者点击鼠标,则游戏重新初始化;如果关闭窗口,则游戏结束。
代码如下
isMid = lambda x, L, R : x < L or x > R
running, gameOver = True, False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
if gameOver:
step, food, head, snake = init()
gameOver = False
# 监听键盘事件
if event.type == pygame.KEYDOWN and event.key in keyDct:
step = updateStep(step, event.key)
# 更新蛇的位置
head = (head[0]+step[0], head[1]+step[1])
# 蛇体增长
snake.insert(0, head)
if head == food:
food = newBox()
else:
snake.pop()
# 绘制游戏界面
screen.fill(BLACK)
if gameOver:
drawGamerOver(screen, font)
else:
drawSnake(screen, snake, food, font)
# 检测碰撞
gameOver = isMid(head[0], 0, WIDTH-1) or isMid(head[1], 0, HEIGHT-1) or head in snake[1:]
pygame.display.flip()
pygame.time.Clock().tick(10) # 控制游戏速度
游戏效果如下
参考文章
发表评论