贪吃蛇(一)

pygame 是python的一个游戏开发的框架,使用起来非常的简单,用于开发小游戏再适合不过了。官方网站是 pygame,大家可以在上面找到许多有趣的小游戏。废话少说,我们开始进入正题。

一、准备工作

  1. 如果你还没有安装pygame,那么就用python的包管理器安装pygame吧!我们的程序用的是python3哦!
    pip install pygame
  2. 首先当然是导入包
    import pygame
  3. 初始化pygame,并且新建一个屏幕,这个屏幕就是一个画布,我们可以再上面画任何东西,我们的贪吃蛇就是要展示在我们的画布上
pygame.init()

WIDTH, HEIGHT = 500, 500
screen = pygame.display.set_mode((WIDTH, HEIGHT))
  1. 设定我们窗口的标题
pygame.display.set_caption("贪吃蛇")
  1. 我们设定一下我们游戏的帧数,就是游戏中常出现的FPS,中文就是,每秒屏幕刷新的次数,这里我们设定为30,同时我们需要一个计时器,计时器pygame内部就为我们提供了,用起来很简单哦!
clock = pygame.time.Clock()
FPS = 30
  1. 一切准备就绪,我们可以开始进入正文啦~~

二、游戏主体

首先看一下下面一个循环:

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 循环时,就会跳出循环咯!这是我们游戏的主循环~
我们看一下效果:


name.png

好了!我们现在已经有一个屏幕了,加下来我们就要画一个方块作为起点,然后我们试着移动这个方块!

绘制一个方块

我们先定义两种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()

效果如下:

贪吃蛇-方块.png

移动小方块

要移动图中的小方块只要判断是否有上下左右键盘按键被按下的事件发生就好了。我们定义四个方向,默认情况下我们将小方块置于屏幕中间,移动方向为向左,然后,我们按下方向键之后,我们就更改方块的移动方向。方块的移动速度和我们的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))

好了!我们现在已经可以移动物体了~

贪吃蛇的身体

现在我们就可以将方块变成贪吃蛇了!我们用一个列表记录贪吃蛇身体的每一个位置,然后我们每次刷新的时候就打印出这个列表~~。并且我们在屏幕中随机产生贪吃蛇的食物,每次贪吃蛇吃到食物的时候我们就将贪吃蛇的身体长度加长一节(在蛇的尾部)。

我们稍微重构一下代码,由于我们的小蛇身体的每一部分都是正方形,我们可以把我们的屏幕分成固定宽度的网格,就像下面那样。

网格.png

看见那个绿色的方块没有~!那个就是我们小蛇的食物啦!

我们定义网格的宽度为 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))

看下效果吧~~

贪吃蛇--初步作品.png

结束

是不是还不错呢~~

完整的代码可以去我的 github 看,点击这里进入GitHub。

下期,我们会继续完善我们的作品,喜欢的就打赏一下吧,你的打赏是我们继续创作的动力哦!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容