pygame 是python的一个游戏开发的框架,使用起来非常的简单,用于开发小游戏再适合不过了。官方网站是 pygame,大家可以在上面找到许多有趣的小游戏。废话少说,我们开始进入正题。
一、准备工作
- 如果你还没有安装pygame,那么就用python的包管理器安装pygame吧!我们的程序用的是python3哦!
pip install pygame
- 首先当然是导入包
import pygame
- 初始化pygame,并且新建一个屏幕,这个屏幕就是一个画布,我们可以再上面画任何东西,我们的贪吃蛇就是要展示在我们的画布上
pygame.init()
WIDTH, HEIGHT = 500, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
- 设定我们窗口的标题
pygame.display.set_caption("贪吃蛇")
- 我们设定一下我们游戏的帧数,就是游戏中常出现的FPS,中文就是,每秒屏幕刷新的次数,这里我们设定为30,同时我们需要一个计时器,计时器pygame内部就为我们提供了,用起来很简单哦!
clock = pygame.time.Clock()
FPS = 30
- 一切准备就绪,我们可以开始进入正文啦~~
二、游戏主体
首先看一下下面一个循环:
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
print(event.type)
if event.type == pygame.QUIT:
running = False
我们运行一下程序看一下效果,会出现一个屏幕,并且点击一下屏幕,屏幕上会打印出所发生时间的类型,而我们点击关闭按钮的时候,就会出发 pygame.QUIT 事件,这是我们就睡将 running 设置为 False,这样再运行到 while 循环时,就会跳出循环咯!这是我们游戏的主循环~
我们看一下效果:
好了!我们现在已经有一个屏幕了,加下来我们就要画一个方块作为起点,然后我们试着移动这个方块!
绘制一个方块
我们先定义两种RGB颜色:黑色 (0, 0, 0) 和白色 (0xff, 0xff, 0xff),然后我们将背景设置为黑色,我们的方块设置为白色!
# 定义两种颜色:
WHITE = (0xff, 0xff, 0xff)
BLACK = (0, 0, 0)
# 将屏幕背景设置为黑色
screen.fill(BLACK)
# 画一个正方形,第一个参数为我们的屏幕,第二个参数为颜色,第三个参数为矩形的位置和大小具体定义为:
# (距离左边界距离,距离上边界距离,宽度,高度)
pygame.draw.rect(screen, WHITE, (20, 20, 30, 30))
# 更新一下屏幕
pygame.display.update()
效果如下:
移动小方块
要移动图中的小方块只要判断是否有上下左右键盘按键被按下的事件发生就好了。我们定义四个方向,默认情况下我们将小方块置于屏幕中间,移动方向为向左,然后,我们按下方向键之后,我们就更改方块的移动方向。方块的移动速度和我们的FPS是有关的。比如我们设定了FPS为30,那么我们就在循环里面设置计数器,当计数器为30的倍数的时候我们才移动一下方块。
# 设置方向
D_LEFT, D_RIGHT, D_UP, D_DOWN = 0, 1, 2, 3
# 贪吃蛇小方块的宽度
CUBE_WIDTH = 20
# 设置计数器
counter = 0
# 设置出事运动方向为向左
direction = D_LEFT
# 设置方块的初始位置
left, top = WIDTH / 2, HEIGHT / 2
# ................................................................................................
# 按键判断
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN: # 如果有按键被按下了
# 判断按键类型
if event.key == pygame.K_UP:
direction = D_UP
elif event.key == pygame.K_DOWN:
direction = D_DOWN
elif event.key == pygame.K_LEFT:
direction = D_LEFT
elif event.key == pygame.K_RIGHT:
direction = D_RIGHT
# 判断计数器是否符合要求,如果符合就移动方块位置,(调整方块位置)
if counter % FPS == 0:
if direction == D_UP:
top -= CUBE_WIDTH
elif direction == D_DOWN:
top += CUBE_WIDTH
elif direction == D_LEFT:
left -= CUBE_WIDTH
elif direction == D_RIGHT:
left += CUBE_WIDTH
# 计数器加一
counter += 1
pygame.draw.rect(screen, WHITE, (left, top, CUBE_WIDTH, CUBE_WIDTH))
好了!我们现在已经可以移动物体了~
贪吃蛇的身体
现在我们就可以将方块变成贪吃蛇了!我们用一个列表记录贪吃蛇身体的每一个位置,然后我们每次刷新的时候就打印出这个列表~~。并且我们在屏幕中随机产生贪吃蛇的食物,每次贪吃蛇吃到食物的时候我们就将贪吃蛇的身体长度加长一节(在蛇的尾部)。
我们稍微重构一下代码,由于我们的小蛇身体的每一部分都是正方形,我们可以把我们的屏幕分成固定宽度的网格,就像下面那样。
看见那个绿色的方块没有~!那个就是我们小蛇的食物啦!
我们定义网格的宽度为 20个像素,然后计算出网格的个数,再定义一个画网格线的函数
# 贪吃蛇小方块的宽度
CUBE_WIDTH = 20
# 计算屏幕的网格数,网格的大小就是小蛇每一节身体的大小
GRID_WIDTH_NUM, GRID_HEIGHT_NUM = WIDTH / CUBE_WIDTH, HEIGHT / CUBE_WIDTH
# ..................................................................................................
# 画出网格线
def draw_grids():
for i in range(GRID_WIDTH_NUM):
pygame.draw.line(screen, LINE_COLOR,
(i * CUBE_WIDTH, 0), (i * CUBE_WIDTH, HEIGHT))
for i in range(GRID_HEIGHT_NUM):
pygame.draw.line(screen, LINE_COLOR,
(0, i * CUBE_WIDTH), (WIDTH, i * CUBE_WIDTH))
接下来我们定义一个列表,代表小蛇的身体,这个列表里存放了小蛇的每一节身体的坐标,然后我们再定义一个画出小蛇身体的函数
# 每次小蛇身体加长的时候,我们就将身体的位置加到列表末尾
snake_body = []
snake_body.append((int(GRID_WIDTH_NUM / 2) * CUBE_WIDTH,
int(GRID_HEIGHT_NUM / 2) * CUBE_WIDTH)) # 添加贪吃蛇的“头”
# 打印身体的函数
def draw_body():
for sb in snake_body:
pygame.draw.rect(screen, WHITE, (sb[0], sb[1], CUBE_WIDTH, CUBE_WIDTH))
我们现在还差一个生成小蛇食物,及画出食物的函数
# 用于记录食物的位置
food_pos = None
# 随机产生一个事物
def generate_food():
return (random.randint(0, GRID_WIDTH_NUM - 1),
random.randint(0, GRID_HEIGHT_NUM - 1))
# 画出食物的主体
def draw_food():
# print (food_pos)
pygame.draw.rect(screen, GREEN,
(food_pos[0] * CUBE_WIDTH,
food_pos[1] * CUBE_WIDTH, CUBE_WIDTH, CUBE_WIDTH))
我们现在还差一个判断是否小蛇吃到食物的函数,那么我么游戏的各个部件就完整了
# 判断贪吃蛇是否吃到了事物,如果吃到了我们就加长小蛇的身体
def grow():
# 这里我们只要简单判断小蛇头部的坐标和食物的坐标是否一致就可以了~~
if snake_body[0][0] == food_pos[0] * CUBE_WIDTH and\
snake_body[0][1] == food_pos[1] * CUBE_WIDTH:
return True
return False
游戏主逻辑
OK!现在我们可以修改一下我们的游戏的主逻辑就完整了~
主要就是更新小蛇身体的各个部位的位置,以及查看是否需要加长身体,最后更新画布!!
# 判断计数器是否符合要求,如果符合就移动方块位置,(调整方块位置)
if counter % int(FPS / 12) == 0:
# 这里需要保存一下尾部的位置,因为下文我们要更新这个位置
# 在这种情况下如果小蛇迟到了食物,需要在尾部增长,那么我们
# 就不知道添加到什么地方了~~
last_pos = snake_body[-1]
# 更新小蛇身体的位置
for i in range(len(snake_body) - 1, 0, -1):
snake_body[i] = snake_body[i - 1]
# 改变头部的位置
if direction == D_UP:
snake_body[0] = (
snake_body[0][0],
snake_body[0][1] - CUBE_WIDTH)
elif direction == D_DOWN:
snake_body[0] = (
snake_body[0][0],
snake_body[0][1] + CUBE_WIDTH)
# top += CUBE_WIDTH
elif direction == D_LEFT:
snake_body[0] = (
snake_body[0][0] - CUBE_WIDTH,
snake_body[0][1])
# left -= CUBE_WIDTH
elif direction == D_RIGHT:
snake_body[0] = (
snake_body[0][0] + CUBE_WIDTH,
snake_body[0][1])
# 判断小蛇是否吃到了事物,吃到了就成长
got_food = grow()
# 如果吃到了事物我们就产生一个新的事物
if got_food:
food_pos = generate_food()
snake_body.append(last_pos)
# 更新一下画布
draw_grids()
# 画小蛇的身体
draw_body()
# 画出食物
draw_food()
到此为止,我们的游戏就开发完成啦~~
看一下效果,还不错哦!
不太舒服,将头改成红色吧~~
# 打印身体的函数
def draw_body():
for sb in snake_body:
pygame.draw.rect(screen, WHITE, (sb[0], sb[1], CUBE_WIDTH, CUBE_WIDTH))
# 将头部改成红色
pygame.draw.rect(screen, RED,
(snake_body[0][0],
snake_body[0][1],
CUBE_WIDTH,
CUBE_WIDTH))
看下效果吧~~
结束
是不是还不错呢~~
完整的代码可以去我的 github 看,点击这里进入GitHub。
下期,我们会继续完善我们的作品,喜欢的就打赏一下吧,你的打赏是我们继续创作的动力哦!