编者按
indienova 会员青铜的幻想为希望了解学习 GameMaker: Studio 的中文读者专门撰写了本系列教程,本文为第三期,本期内容将教会大家如何在 GMS 中添加场景的背景及场景中的物品。欢迎读者朋友在文章后留言,以便作者能够针对性地安排接下来的教程内容。
说明
前两期教程的传送门:
本期概述
前一次的教程演示了从零开始,如何在 GMS 中加入一个能够由玩家控制行走的游戏角色。在本次教程,我们将要把这个角色放入游戏场景中。教程所选用的场景素材来自独立游戏《冰杖秘闻》的洞穴世界场景:
但为了讲解方便略微减少及简化了部分素材。
教程目标
这次教程的内容是学会在 GMS 中添加场景的背景及场景中的物品。
准备工作
想要学习一个游戏引擎,最好的方法就是亲自动手去做。我希望想要跟着这个教程来学习 GMS 的同学不光只是看一遍而已,而是能够把文中提到的每一个操作都实现一遍。所以我会附带实现每篇教程的内容所需的资源和项目文件。
这次的内容是在上一次教程的基础上来继续开发的,所以没有从上一篇教程开始的同学可以直接在这里下载上次的完整项目文件:教程项目地址。
解压后的 GMS_TUT_01 文件夹中为上一篇教程的项目文件和美术资源,而本次教程所用的美术资源可以在这里单独下载:美术资源地址。
场景背景
GMS 在资源导航栏中设立了一个分类叫做 Backgrounds,用于加载背景图片到场景中。其导入过程类似 Sprites。我们先导入背景图到 GMS 中,因为该场景名为“洞穴世界”,故命名 bk_cave
:
洞穴世界场景的大小我们设定的是 1440x900,这也是背景图的大小。因此我们要更改上一次添加的测试 Room 的大小,然后将刚刚导入的图片设为它的背景:
场景中的物品
剩下的美术资源均为场景中会用到的物品,包括动态的:草、路灯的光、水池,以及静态的:雕像、木桶、墙和血池。
导入方法和上一次教程中导入人物动画的步骤一样,导入后按照上图顺序分别命名为:
- spr_grass
- spr_light
- spr_pool
- spr_statue
- spr_barrel
- spr_wall
- spr_blood_pool
下图示范了 spr_grass
的添加,对于具有动画的物品需要选择所有动画的图片帧,而静态物品则只有一张图片。
在上面这个动图的最后,我反复调整了两次草的原点坐标,下面我们要专门讲下这个步骤。
Sprite 的原点
在添加Sprite过后,正确的选取物品或者人物的 Sprite 原点是很重要的一个步骤。对于某些类型的游戏,例如飞行射击游戏或者顶视角的2D游戏,通常会直接选取图片的中心做为原点。但对于《冰杖秘闻》这样的 2D ARPG 来说,会更多的从三维场景的角度来选择原点,即选择物品底部平面的中心点来作为原点(尽管底部平面常常是不可见的,但我们需要想象到那个点的位置)。 我以场景中的木桶为例来说明为什么要这样做:
-
原点应当表示物品的实际位置
可能光凭文字你难以感受到我想要表达的意思,不如我们来看一个例子。假设现在游戏有一个功能是可以通过用鼠标点击地面来放置一个木桶。如果我们如下图所示选择木桶图片的中心点来作为原点(选择中心点做为原点可以通过点击 Origin 设定框下方的 Center 按钮来快捷完成,所得原点为右边红色交叉线的交点):那么此时点击放置木桶的效果如下:
应该可以注意到,这样做的结果非常不自然,因为鼠标点击的位置是地板格的交叉点,但从三维感受来讲,木桶却并不是出现在交叉点上。那么如果我们把原点改为木桶的底部中心点(右侧红线的交叉点):
这样效果就好多了,木桶正确的出现在鼠标所点击的位置上面。
-
原点是物品缩放和旋转的参考点
同样以木桶为例,假设场景中事先并排放置了三个木桶:如果由于游戏设置的需要,要把第二个桶变大,把第三个桶放倒。这意味着增大第二个桶的缩放系数,将第三个桶向右旋转90度。
那么这是原点位于图片中间时的情形:这是将物品底部中点设为原点的情形:
毫无疑问,第二种情况更为合理。因为缩放和旋转是不应当改变物体的位置的,在变换后,原本水平排布的三个木桶应该依然保持水平。
上面我们花费了一些篇幅来讲 Sprite 原点的设定,其核心原则就是将物体底部的中心点作为原点。类似的例子还有将人物双脚连线的中点作为人物的原点等。而且用一致的方式来设定所有物体的原点,将会为之后的物体间遮挡关系的计算提供便利,这一点将在之后的教程里详细阐述。
资源分组
在你将本次教程所附带的场景资源全部导入为 Sprite 后,你的资源导航栏中的 Sprites 分类应该具有以下项目,即上次课所用到的4个伊瑟拉的人物动画和7个这次加入的场景物体:
仅仅是两次课程的内容就已经有了一共11个不同的 Sprites,可以预见在真正的项目过程中,这个列表很快就会变得无比冗长。如果全部平铺显示在 Sprites 类别中,将难以对资源进行查找,所以将资源归类是十分必要的。但具体的归类方式并没有什么唯一正确的方法,只要能方便查找到所需资源即可。这里我们可以将上述 Sprites 分为 Character(角色)、StaticObject(静态物体)和 DynamicObject(动态物体)三类:
之后,不仅仅对 Sprites,对其他资源类别,也可以在需要的时候加以归类来令项目更加整洁可维护。
创建 Object
在上一次的教程中,我们已经演示过了如何创建 Object。因为在 GMS 中,任何 Sprite 都必须以一个 Object 作为载体才能放入场景中,所以这里需要为每个场景物体建立一个 Object,具体过程不再赘述。当建立完毕后,资源导航栏中的 Objects 类别应该包含以下 Object:
可以看到我这里所有 Object 的命名与其对应的 Sprite 一致,唯一的区别就是前缀由 spr_
换成了 obj_
。
场景中 Object 的放置
当建立好了所需的 Object 之后,就可以开始场景的布置了。在 GMS 中放置物品的步骤是首先在 Room 的 Objects 设置面板中选择你想要放置的 Object,下图中我选择的物品是木桶(obj_barrel
):
然后直接在场景中左键点击即可:
大部分物体,你可以自由发挥来决定其所在的位置。但对于雕像和墙壁来说,由于我们的背景图中预先渲染了它们的阴影,因此要仔细的对齐:
注意场景的网格对齐参数:
在上面一个动图中,由于之前的网格大小为32,物体的坐标只能是32的整数倍,因而无法很好的对齐它的阴影,所以我把它改成了1来做精细的位置调整。这个需要根据具体情况来调整。
还有一个可以教给大家的小技巧,如果有一个物品(通常是光照或者前景等面积较大且相当一部分为透明的物品)挡住了你想要放置新的物品的位置,这个时候你点击鼠标左键将会选择到原有的物品而非新建物品。这是你可以用 Ctrl + 鼠标左键来将新的物品放置到原有物品之上:
在这个动图中最后三株小草就是通过 Ctrl + 鼠标左键添加的。
将所有我们新建的物品都放入场景中以后就是这样的了:
动画的设置
如果这时你试着运行游戏的话,就会发现鬼畜的小草摇动和水池波动…… 所以还需要对几个动画做些调整。首先是为小草和灯光这两个动画添加反向播放的动画片段。以小草的摆动为例,在制作动画的时候,在美术资源上只需要小草从一侧摆到另一侧的图片即可,而剩下的一半可以通过反向播放这些图片来完成整个动画循环。灯光的闪烁也是同理。而GMS很贴心的提供了一个Add Reverse的功能来实现:
在为 spr_grass
和 spr_light
添加完反向动画以后,还需要设置一下它们的动画速度。还记得在上一次教程中设置过的这个参数吗?就是 image_speed
。因此我们要在 obj_grass
、obj_light
和 obj_pool
这三个 Object 被创建的时候,设置这个参数的数值,这里用对 Create 事件写一个脚本来完成:
下集预告
这时我们可以试试看运行当前的游戏,是不是已经很有感觉了呢?
但其实现在的场景只是看起来还不错而已,还有一些 APRG 游戏中必要的功能没有加入,包括:
- 物体间的碰撞处理
- 物体间的遮挡关系
- 摄像机的跟随
下一篇教程将会陆续解决这些问题。
附录:教程资源链接
该系列教程的项目/代码及原始美术素材全部更新至 GitHub 项目库。
本次教程的美术素材下载包则见这里。
写得真棒!!
现在每周就等大大你的教程更新了!!
加油!!
学习!
不能把素材放在一张大图里吗?
@BrotherShort:是可以的,在新建Sprite后,打开Sprite Editor,然后用“create from strip”来从大图中导入动画。但我个人认为这样比分开的图片更麻烦。
@BrotherShort:我记得 gms 会在打包游戏时可以自动完成这一步(至少导出 html5 时是这样的,忘记需不需要设置了)。为了降低包体大小而降低开发效率是不可取的。像 minecraft 早期的贴图素材都在一张大图上,结果拓展的时候不方便加新的 items,目前的版本也全做成分开的贴图了。
请问有什么GameMaker: Studio 素材网站一类的推荐么
@Cloudmy:游戏开发相关的资源可以到这里查到一些,大部分是开源的,可以免费获得使用许可:http://indienova.com/sp/gameDevResource
大大,个人建议小草这样别用实例(object),用draw函数。实例会很浪费cpu资源的。当然如果就简单这么几个实例,没什么。不过良好的习惯就应该从最初开始。
@Aprilbuble:目前游戏开发工具的发展潮流是面向开发效率友好而不是面向性能友好的,因为机器性能越来越好,程序猿的开发时间却越来越值钱。使用绑定 sprite 的 object 固然比直接 draw 动画有性能开销,但现代机器上这种程度的挥霍几乎不会对游戏的实际表现造成影响,却能够在开发过程中提供大量的便利,未来的扩展也很方便。在完成设计后可以进行适当优化,但过早优化肯定是万恶之源。
@Aprilbuble:谢谢你的提议,我还真没想到这一点。不过原因是因为我们实际的项目是在初期就设定了很多环境物品都是可以交互的,有些类似Enter the Gungeon那样,比如这个小草是可以被踩碎/打掉的,所以从一开始我就是用单独的object来实现的 ^_^
@Ibot:哈哈,谢谢你的回答。相当同意你的观点,对独立游戏来说更是这样。很少有独立游戏是要拼性能的,可维护性和扩展性才最重要!
靴靴大大! 这比视频教程还方便啊。
感谢青铜大大的分享,学完打卡。
感谢您的分享~
大神啊,,谢谢分享学习!膜拜
大大,请问调节动画速度中“image_speed=0.1;”这里的0.1是什么单位呢?秒吗?
在Sprite Editor界面下方把原来的Speed=30设成Speed=3
与在代码里面把image_speed=0.1是一样的表现效果,都是把播放速度缩小为十分之一(0.1) @小头天天:
膜拜daolao
大大 gamemaker studio2里面没有background了,是不是直接在room的background layer里面
@scenerykk:这个在哪啊