GameMaker: Studio 中文教程 #2: 2D人物行走

作者:青铜的幻想
2016-07-27
34 60 48

编者按

indienova 会员青铜的幻想为希望了解学习 GameMaker: Studio 的中文读者专门撰写了本系列教程,本文为第二期,主要对这款引擎的界面功能进行了简单介绍,并结合实例讲解如何制作一个 2D 游戏人物行走图。欢迎读者朋友在文章后留言,以便作者能够针对性地安排接下来的教程内容。

说明

各位好~之前的一篇教程简单介绍了 GameMaker: Studio 这款引擎,并讲解了从官网免费下载并注册使用 GMS 的过程。如果还没有看过或者觉得有些生疏了,可以前往这里复习一遍。

从本篇开始,我迫不及待地要进入具体的开发教程了,我将结合实例,详细为大家展示使用 GMS 开发游戏需要掌握的知识与技巧。

教程素材来自目前与胡桃工作室合作的独立游戏《冰杖秘闻》(The Tale of the Ice Staff)(中文站点见这里)。

目前该游戏已通过 Steam 的 Greeelight,大家有兴趣可以关注:

我将开发内容整理成教材,是希望能够对有兴趣开发独立游戏的朋友们有所帮助,后续教程也会陆续发表在 indienova 上。

本期概述

教程目标

完成本教程,可以学会在 GMS 中加入一个能够四方向行走的 2D 游戏人物。

所需素材

所需要的美术资源是《冰杖秘闻》女主角之一伊瑟拉的正面、背面和侧面的行走动画以及站立动画(本文所用到的全部美术资源可在文章后面的链接下载,也可以访问本教程项目的 github 库):

image18
image23
image08
image03

值得一提的是虽然人物的行走是四个方向,但往左右方向行走的时候通常可以用同一个侧面行走动画来表现。这样做的问题在于细心的玩家会发现为什么有时主角的武器拿在左手,有时又拿在右手呢?不过没关系啦,因为自古以来 2D 游戏业界通常都是这么做的,好像没有发生过玩家因此而不满的事件。

新建项目

如果这是你第一次打开 GMS,你需要新建一个项目,我把这个项目叫做 Tutorial01:

image01

而之后 GMS 会在欢迎页面记住这个项目,所以当你下一次继续你的项目时,只需要在欢迎页面点选你的项目即可:

image22

GMS 界面功能简介

image16

如图中标注,在进入 GMS 后,其大概的模块分为三个部分:

  1. 菜单及工具栏 (红色区域):所有命令或操作都集中在这里,例如保存游戏、创建新的资源等;
  2. 资源导航栏 (黄色区域):游戏中所有用到的资源都放在这里,例如 Sprites 动画、Objects、Rooms 等,以类似 Windows 资源管理器的方式存放和管理;
  3. 工作区 (蓝色区域):所打开的窗口编辑器所在的位置,例如 Sprite 编辑器、Objects 属性编辑器或者脚本编辑器等。

术语解释

  • Sprite:Sprite(精灵) 一词首次作为计算机图形术语出现,是在德州仪器的 9918(A)视频显示处理器上。之所以采用这个词作为术语,是由于在古早时期,这类资源并不会放入图形处理器的帧缓存区中,而是在显示时再与背景图层组合,就好似悬浮在空中一样。目前,这个术语的使用范围已经脱离了这层含义,用来泛指包含于场景中的各种 2D 图像或动画。简单地理解,Sprite 可以是一组多帧的 2D 图像,我们可以在游戏中控制它的显示位置,大小,角度,动画播放的速度和当前播放哪一帧动画。在本教程中,2D 人物的行走动画就是通过 Sprite 来表现的。
  • Object:Object(对象)的概念来自面向对象编程(OOP)。将数据和对其进行的相关操作封装起来,就得到了 Object(对象)。面向对象编程,就是将程序分解为互相通信的 Object 模块的编程范式。对象有机地将数据和数据的行为组织了起来,非常便于模拟一类事物,在游戏编程中这种特点能够发挥巨大的威力。GMS 中的 Object (对象),可以用来表示游戏中的一类事物以及与它们相关的行为,是我们创造游戏世界最基础的单元。
  • Room:GMS 以 Room (房间)为单位来管理游戏,类似其他游戏引擎中的场景(Scene)。所有的 Object (对象)都是会加载到某个 Room (房间)中来执行。如果把游戏比作戏剧,Room 就是演出的舞台。

这一点也与 Windows 操作系统类似,通常 GMS 中的同一操作可以通过菜单、工具栏和资源导航栏的右键菜单以及快捷键等多种方式来完成。

以创建一个 Sprite 来说,就分别可以用以下不同方式来进行:

  1. 在资源导航栏 Sprites 分类的右键菜单中选择 Create Sprite(我最常用的方式):
    image25
  2. 点击工具栏中的吃豆人图标:
    image24
  3. 选择菜单栏命令 Resources -> Create Sprite:
    image12
  4. 使用快捷键(Shift+Ctrl+S)。

导入Sprites

制作游戏内容的第一步通常从导入相关美术资源开始,对于我们所要做的2D场景中的人物伊瑟拉,其美术资源是她的 Sprites 动画。

这里值得一提的是在使用 GMS 开发时需要注意的命名规则问题。因为所有的游戏资源,不管是 Sprites、Objects 还是 Rooms 都是可以在脚本代码中直接使用名字引用的,而在 GMS 所用的脚本语言 GML(Game Maker Language)中,变量可以容乃任意类型的数据(而不是像 Unity 所用的 C# 一样需要事先定义变量的类型)。所以如果我们不对资源的命名加以规范化,就会容易在代码中陷入混乱,搞不清楚当前变量的类型了。

一种大家都在使用的命名规范就是在每个资源名称前加入一个代表该类别的前缀:例如 Sprite 前加 spr_,Object前加 obj_,Room前加 rm_。然后在后面加上用下划线分隔的用于标注该资源内容的单词。按照这样的规则,我们所导入的伊瑟拉的站立动画的合适的名字应该是 spr_ysera_idle,而行走动画需要区分方向分别命名为 spr_ysera_walk_frontspr_ysera_walk_backspr_ysera_walk_side

导入一个 Sprite 资源的操作如下:

image06

在这个打开的Sprite属性窗口中,目前我们需要关注的是下图两个红框中的信息。上面是该Sprite的像素宽度和高度,总帧数以及当前所显示的帧编号,点击两个指向左右的绿色箭头可以切换当前所在帧从而浏览整个动画。下面这个红框所包含的是该Sprite对应物品的原点。

image02

将该 Sprite 的原点值改为X=80、 Y=120(即人物的双脚中间的位置),然后点击 OK,即可完成第一个 Sprite 资源的导入。

image13

然后按照同样的方式导入剩下三组行走的 Sprites 动画之后,你的资源导航栏里应该是这样的:

image26

创建 Object

GMS 中的 Object 是组成游戏的基本单元,类似 Unity 中的 Prefab,可以理解成游戏中所出现物品的模板。我们为将要加入游戏中的角色伊瑟拉建立一个 Object,按照之前提到的命名规则,把这个 Object 叫做 obj_ysera。并将该 object 的 Sprite 属性选为 spr_ysera_idle,这样当角色被放入场景后,将会默认播放站立动画。

image20

创建 Room

Room 对应游戏的场景,我们暂且先建立一个叫做 rm_test 的测试场景用于查看我们的新加的游戏角色。

image04

在 Room 中加载角色

随后,我们将之前建立的 obj_ysera 放入测试场景 rm_test 中。

image07

首次测试运行

在建立了场景并放入角色后,我们就可以点击工具栏中的绿色播放按钮试试运行一下当前游戏看看效果如何了。

image11

如果这是你的第一次运行,GMS 可能会花数秒的时间来编译,这个时间会随着你的游戏中的资源增加而变长。之后你就可以看到 GMS 的 logo 出现,随后是我们刚刚建立的灰色测试场景与我们的游戏角色伊瑟拉。你会发现目前人物的站立动画快的如同抽风一般,没关系,这是因为我们还没有调整过动画的播放帧率。

新建控制脚本

接下来我们需要通过建立脚本来响应玩家的输入并移动 obj_ysera

脚本也属于游戏资源的一种,放置在资源导航栏的 Scripts 目录下。GMS 使用了一套 Events/Actions (事件/动作)的系统来完成脚本对 Object 的控制:简单地说,就是当这个 Object 身上发生了一件什么事情的时候(Event),来对应执行一个什么动作(Action)。举个例子,假如我们现在需要人物被攻击而受伤的游戏逻辑,我们会添加这样一组 Event/Action,即当人物与子弹碰撞时(Event),将人物的生命值减去5(Action)。而对于角色移动的逻辑来说,需要在游戏的每一帧都去做出判断玩家的按键情况,因此这里要用到一个叫做“Step”的 Event,这个 Event 所对应的 Action 会在每一帧都被执行。

GML
GMS 中的游戏逻辑围绕 Event/Action 系统来编写,它提供一套面向新手的拖拽式系统,可以做出逻辑比较简单的小游戏。但想要更加自由地发挥创造力,需要用到 GMS 内置的脚本语言 GML。通过 GML 为你想要实现的游戏逻辑编写脚本(通过拖拽系统编写的 Action(动作)和通过脚本编写的 Action(动作)可以混合使用)。一些相对底层和通用的功能都可以通过调用 GMS 提供的内置函数来完成(即所谓的应用程序开发接口 API),你也能够以此为基础编写复杂而强大的自定义函数。

GML 脚本能够在游戏的很多地方执行:

  • Events(事件):Object(对象)内置了许多事件,你能够通过脚本来控制这些事件出现时Object(对象)的行为和状态;
  • Room Creation Code(场景载入阶段):GMS 能够在场景加载阶段执行你编写的脚本来控制游戏逻辑,你可以认为 Room (房间/场景)在创建阶段会出现一个特殊的事件;
  • Instance Creation Code(实例创建阶段):将以对象为模板的游戏元素加载到场景后,就生成了实例。GMS 能够在实例生成的阶段执行你编写的脚本来控制游戏逻辑。

至于脚本的命名,我个人没有延用与 Sprite、Object 类似的命名规范。因为在这里脚本更像一个个的函数,因此我喜欢用 DoSomething() 这样的函数命名风格,即每个分词首字母大写的动宾短语,这样可读性更好,例如 FireBullet()TakeDamage()。而这个在每个 Step 控制伊瑟拉行走的函数,就叫做 YseraStep 好了。建立一个名为 YseraStep 的脚本:

image17

控制脚本内容

在写具体的脚本内容之前,需要介绍一些 GMS 内置的 Object 的函数和属性。

  • keyboard_check(ord('A')):检查键盘的A键是否被按下。这里其实是两个函数 keyboard_checkord 的组合,其中 ord 函数的作用是返回一个字符的编码值,通常在检测字母按键的时候都会将这两个函数联合起来使用。
  • xyObject 在 Room(场景)中的坐标。

这里使用常见的 WASD 键位来移动角色,具体脚本如下:

if(keyboard_check(ord('A')))
{
    x = x - 4;
}

else if(keyboard_check(ord('D')))
{
    x = x + 4;
}

else if(keyboard_check(ord('W')))
{
    y = y - 4;
}

else if(keyboard_check(ord('S')))
{
    y = y + 4;
}

关联脚本与事件

在写好 YseraStep 这个脚本后,接下来要做的是将其关联到 obj_ysera 的 Step 事件。首先第一步是打开 obj_ysera 的属性面板并添加 Step 事件:

image19

第二步是选择要做的 Action,这里简单介绍一下 GMS 的 Action 面板:

image10

这里右边竖排的标签栏对应的是 Action 的分类,例如 move-移动、score-分数等等预先设置好的分类,左边是该分类下的具体 Action。可能有些人在制作游戏的时候会大量使用这些预先设计好的功能,但这样的问题在于当游戏项目的规模增大时,将会缺乏灵活性、无法搜索并且难以管理,具体的原因估计要单独用一整篇文章来说明。这里我直接建议大家,对于所有的 Event,均使用 Execute Code(执行代码)这一 Action 来处理,这个 Action 在 control 分类下,如图:

image14

将这个 Action 拖动到 Step 对应的 Actions 内容中,将会打开一个代码编辑器用于填写这个 Action 的内容,这个 Action 的内容就是执行刚才的脚本 YseraStep:

image21

运行游戏查看角色移动

再次运行游戏,这时你已经可以使用 WASD 来控制角色的移动了:

image15

动画切换

可以注意到现在角色虽然有了移动,但没有在移动时播放对应的动画。那么下一步我们需要为 obj_ysera 添加动画和人物方向切换的代码。
回到我们刚才所添加的脚本 YseraStep,将代码修改如下:

if(keyboard_check(ord('A')))
{
    x = x - 4;
    sprite_index = spr_ysera_walk_side;
    image_xscale = 1;
}
else if(keyboard_check(ord('D')))
{
    x = x + 4;
    sprite_index = spr_ysera_walk_side;    
    image_xscale = -1;
}
else if(keyboard_check(ord('W')))
{
    y = y - 4;
    sprite_index = spr_ysera_walk_back;    
}
else if(keyboard_check(ord('S')))
{
    y = y + 4;
    sprite_index = spr_ysera_walk_front;
}
else
{
    sprite_index = spr_ysera_idle;
}

其中用到了 Object 的两个新的属性:

  • sprite_index:当前所要显示的 Sprite 动画;
  • image_xscale:图像在 x 方向的缩放,这里把它设置成1和-1来调整人物的左右朝向。

改好之后再次运行:

image05

现在唯一的问题就是动画播放速度太快了。

调整动画播放速度

Sprite动画的播放速度通过变量 image_speed 来控制,把以下代码加入 YseraStep 脚本中即可:

image_speed = 0.25;//使用1/4的速度播放sprite动画

image00

TADAAAA!

image09

经过漫长的劳作,你们终于用自己勤劳的双手做出了第一个 GMS 的 Demo,恭喜!

接下来的教程的内容将涉及到如何添加场景的背景和物品,我们下一期见!

附录:教程资源链接

该系列教程的项目/代码及原始美术素材已更新至 github 项目:

https://github.com/akane2002/GMS_TUT

美术素材可以点击这里下载。

近期点赞的会员

 分享这篇文章

您可能还会对这些文章感兴趣

参与此文章的讨论

  1. 黑轮酱 2016-07-27

    再次跪求1.4闪退的解决办法,WIN7。STEAM正版的GMS。

    • 青铜的幻想 2016-07-27

      @黑轮酱:我自己没有碰到过。你是每个项目都这样吗?

    • BrotherShort 2016-07-31

      @黑轮酱:我的也老是崩溃。

    • 黑轮酱 2016-08-03

      @青铜的幻想:是的,最近别人说可能是因为是steam版的问题,让我换成官网版本。

    • 黑轮酱 2016-08-03

      @BrotherShort:你用的也是steam版本么?

    • BrotherShort 2016-08-04

      @黑轮酱:是的,启动会弹出什么网站证书过期,用着用着就突然没了。

    • 黑轮酱 2016-08-11

      @BrotherShort:证书那个我常年遇到……官网版本那个应该也有证书的问题。

    • doodle 2016-08-27

      @黑轮酱: 你好,请问换上官网版本了嘛?我也是steam版本5分钟一闪退

      但是官网我无法注册啊,register页面会跳到login页面,然后那里的注册只能输两次邮箱账号,根本看不到下面的密码和验证等填空栏。求帮助T T

    • yshxm 2016-08-29

      @doodle:以兼容模式运行steam试试吧,以离线模式运行steam就没有证书问题了

    • doodle 2016-08-30

      @yshxm:好的,感谢建议。我去试试,再不行就去官网搞个版本啦。。

  2. 这个系列好棒~

  3. 了脚喵 2016-07-29

    教程很赞!支持一个!
    一点点小建议,只是个人建议啊,就是先用不需要写代码的"拖拽"方法帮助新人熟悉界面培养兴趣,然后再逐渐深入。上来就教 GML 可能会把没见过代码的初学者吓跑~

    • 青铜的幻想 2016-07-30

      @了脚喵:感谢支持啊~ 其实我也有纠结过这个问题,但最后我真的觉得“拖拽”不是一种能够真正在独立游戏中使用的开发方式,稍微上一点规模以后项目就没法管理了。而且那样的话就应验了大家对GMS的一贯印象,就还是开发游戏的“玩具”,而不是真正能够使用的开发工具。

      但你说的也确实是很有道理的…… 只能希望真正有开发独立游戏愿望的新人能够不畏艰难,直面代码 ^_^

    • 小头天天 2016-11-28

      感谢青铜大神~

    • 李穆阳 2017-02-13

      谢谢!
      对于【不需要写代码的"拖拽"方法】和【当前的方法】,个人觉得【当前的方法】更好

  4. rick343 2016-07-31

    我有点担心新人只会模仿,做不出自己的游戏,或许这个问题会在以后自己消失
    =====================
    对新人的话:新人绝对不要直接复制别人的代码,一定要自己打

    • 青铜的幻想 2016-08-01

      “对新人的话:新人绝对不要直接复制别人的代码,一定要自己打”
      @rick343:简直不能再赞同了!
      我喜欢的一句来自Matrix的台词,“There's a difference between knowing the path and walking the path."

  5. Cloudmy 2016-08-05

    非常感谢作者的教程,尤其是搭配的动图细致到位,期待更新,另外有其他类似的GMS教程推荐么,英文亦可只是第一期推荐的教程都没有这篇这么详细。

  6. KTrendeez 2016-08-08

    请问教程中的sprite和object原件是用什么工具制作的

    • 青铜的幻想 2016-08-13

      @KTrendeez:这个是项目的美术提供的,我不太清楚呃...

  7. forxidian 2016-08-17

    非常感谢!已经按照教程实现出来了!
    感觉自己再去网上找一些脚本和素材,可以做最简单的游戏了呢。

  8. wubinbin0403 2016-08-18

    非常的赞,感谢作者

  9. SandCas 2016-08-31

    感谢大触的教程!

    最近由 SandCas 修改于:2016-08-31 21:34:04
  10. twocold0451 2016-09-01

  11. twocold0451 2016-09-01

    没有问题了

    最近由 twocold0451 修改于:2016-09-01 23:06:33
  12. Zumi 2016-09-05

    编者你好.这个代码是我找到的八方行走的代码,是写在角色事件 步里面的,如果要添加八方行走图的话 该怎么弄呢?

    创建 sp=4


    var dirr;
    var spdd;
    dirr=5;
    spdd=sp;
    if(keyboard_check(vk_shift)){spdd=spdd/2;}
    if(keyboard_check(vk_up)){dirr=dirr-3;}
    if(keyboard_check(vk_down)){dirr=dirr+3;}
    if(keyboard_check(vk_left)){dirr=dirr-1;}
    if(keyboard_check(vk_right)){dirr=dirr+1;}
    switch(dirr)
    {
    case 1:x=x-0.7*spdd;y=y-0.7*spdd;break;
    case 2:y=y-spdd;break;
    case 3:x=x+0.7*spdd;y=y-0.7*spdd;break;
    case 4:x=x-spdd;break;
    case 6:x=x+spdd;break;
    case 7:x=x-0.7*spdd;y=y+0.7*spdd;break;
    case 8:y=y+spdd;break;
    case 9:x=x+0.7*spdd;y=y+0.7*spdd;break;
    }

    最近由 Zumi 修改于:2016-09-05 17:46:05
    • 青铜的幻想 2016-09-05

      @Zumi:这样的话你的角色就会有8个不同的sprite,在你上面代码的8个case语句里把你的sprite_index设置成对应的sprite就好了

  13. x360656112 2016-09-07

    感谢青铜大神的分享。

  14. 不高冷的学渣 2016-09-07 Steam 用户

    青铜的幻想,我想请教一下:像素画是使用什么软件画的呢?

    • 青铜的幻想 2016-09-07

      @不高冷的学渣:呃,这个没法回答你啊…… 是美术提供给我的资源

  15. QWEQWE199706 2016-09-18 新浪微博会员

    最近考虑做个游戏,循环辗转于各种语言各种引擎,这篇文章帮了我大忙了,居然还分享了源码真是不给赞说不过去!

  16. 坏孩子 2016-10-08

    收益匪浅,感谢了

  17. ZFzhou 2016-10-10

    Steam的GMS闪退可以在属性中选择测试退回以前的版本,最新版好像部分会闪退,退回以前的版本就不会了。

  18. Xlion 2016-10-12

    可是这么写的话有一个问题,角色停止移动的时候脸会自动转向正面,左右行走的话还好,向上行走的话有点鬼畜啊......

    最近由 Xlion 修改于:2016-10-12 15:31:12
    • Xlion 2016-10-13

      @Xlion:自己想了一个办法解决这个问题,就是与上一步坐标比较:
      else if (x < xprevious) //静止时面向左
      {
      sprite_index = spr_stand;
      image_xscale = 1;
      }
      spr_stand是一个面向左边的站立图,以此类推

    • B102 2016-10-16

      @Xlion:
      if(keyboard_check(ord('A')))
      {
      phy_position_x = phy_position_x - 4;
      image_speed = 1;
      sprite_index = spr_Player_Walk_L;
      }
      else if(phy_position_xprevious>phy_position_x)
      {
      image_speed = 0.10;
      sprite_index = spr_Player_Stand_L;
      image_xscale = 1;
      }
      没反应啊怎么弄

      最近由 B102 修改于:2016-10-16 16:31:47
  19. 3gePSmSN 2016-10-15 Steam 用户

    绿色播放按钮点了以后没反应啊,下面提示Compile finished: 23:50:48

  20. aihidao 2016-12-13

    在创建了多个room时候,如何确定开机使用哪个room?

  21. tony 2017-01-02

    感谢 希望有更多的教程 indienova一定会越办越好 哈哈

  22. TomasLiu 2017-02-24

    太感谢了 如此详细清楚

  23. q312092921 2017-03-13

    真的是非常感谢,这套教程帮助了我不少。

  24. VDerGoW 2017-04-12

    照着这节做完后,启动游戏人物是idle那个状态的动画,但是使用按键操作人物移动之后,松开按键人物不会自动回到idle状态的动画,一直播放按键对应的动作动画,请问这是什么原因?

    • VDerGoW 2017-04-13

      @VDerGoW:马虎了,以为后来给的代码和前面的是一样的,原来又加了一个else恢复初始状态。

  25. biibibibibi 2017-06-07

    = =来学习一下!~~~

  26. **狸花猫 2017-09-03

    结尾PP好评
    虽然这不是重点

  27. dangchuchange 2017-09-29

    问下上左,下左,上右,下右的图片怎么实现,现在是4个if无else,但是图片只会按顺序为最后的显示,想要实现
    如果先按上同时再按左,则显示back图,先按左同时再按上,显示左侧面图,请问这个如何搞哦~

  28. ltzibaozhe 2018-03-05

    请问大神如果是上45度楼梯时是不是要锁定行走的方向(45度斜着走),希望能讲一下怎么做。

  29. 缚瞳默 2018-05-14 微信会员

    发现个小问题,我用GMS2写这个脚本时,发现如果(keyboard_check(ord("A")))这里的A用单引号‘’时,会报错,双引号才能通过。希望作者大大能更新下~

您需要登录或者注册后才能发表评论

登录/注册