GameMaker Studio 2

创建于:2017-04-19

创建人: dougen

142 信息 436 成员
游戏开发工具 GameMaker Studio 2 的讨论小组

译文:GAMEMAKER STUDIO系列:Timer

highway★ 2018-11-09

Image title

依旧面向新手

译注:非完全翻译,有些片汤儿话就不翻了,只翻重点 :p ,我对部分代码进行了补充,加上了对应事件位置和注释,方便gml初学者理解操作,我在读原文的过程中有些地方比较困惑,自己适当修改了一下文章的内容。如果有错误出现,麻烦指正。感谢!

作者:Nathan Ranney

翻译:highway★

如果你看过我之前的文章,应该会注意到我用了很多自定义的计时器,而不是GMS内置的alarm系统。我这么做的原因是,一呢~ GMS的alarm数量上有限制,二呢~ 并不是很直观,有时候写着写着我就记不住alarm[0]里面写过什么,当东西一多,就容易乱套。

(译注:当你的项目越来越大越复杂,可能会用到很多timer,这时候一个个打开alarm去查看很容易让人……怎么说?懵逼? 或许更严重,尤其是你的显示器不够多不够大,想想以前GMS1的IDE,打开无数个窗口……wtf,如果你用自定义的timer,一个窗口就全看的到,很直观~ 当然,最好灵活的使用region,可以让代码更加整洁)

译注:下面的示例,请确保游戏以60fps运行,如果你对GMS2还不熟悉,可以在屏幕右侧Resource最下方找到Option选项,点击Main,在弹出窗口中可以看到Game frames per second。

概述和设置

那究竟什么是Timer(计时器)呢?Timer是一种机制,允许您向上或向下计数到某个值,然后在达到该值时触发某些内容。例如,假设你的角色被毒性伤害攻击到了。毒性伤害通常是随着时间的推移,每隔一段时间就会造成少量伤害。想象一下你的游戏以每秒60帧的速度运行,你决定毒药伤害应该是1点伤害。你的角色有100点血量,你的代码看起来像这样:

示例代码:

//Create event
poisonDamage = 1;

//Step event
if(poisoned){
hp -= poisonDamage;
}

这段代码里没有Timer或任何其他限制,它每秒以60fps(游戏每秒60帧)的速度将你的hp降低1。这意味着......你的角色有100点血,在1.6秒内死掉!oh,shit,这毒也忒tm狠了吧?你可不想这样,对吧?你真正想要做的是每隔几帧对你的毒害造成伤害,或者每隔几秒。那么代码应该看起来像下面这样:

示例代码:

//Create event
poisonDamage = 1;
poisonTick = 60;//补充,原文并未初始化

//Step event
if(poisoned){
poisonTick --;


if(poisonTick <= 0){
hp -= poisonDamage;
poisonTick = 60;//重置Timer
}
}

译注:请确保option里游戏是以60fps运行

这里,我使用一个新变量poisonTick来确定何时应用毒害。所以现在,之前要1.6秒,现在需要60秒。 poisonTick每帧减少1,一旦poisonTick达到0,玩家hp将减少poisonDamage值,并且poisonTick将重置为最大值60。这需要比使用alarm稍微复杂一点点,但更好用。

要以这种方式使用Timer,您至少需要一个变量,该变量存储你正在计算的任何内容。在上面的例子中是poisonTick。我强烈建议你在重置计数变量时使用第二个变量。这会更方便管理(译注:当你自己的小项目进行了一段时间,重新打开并查阅代码时候,如果你看到一堆数字,可能早已经忘了当时写下它的具体含义了,所以能用变量就用变量,变量名可读性越高越好,如果你不是solo开发,你可不想你的战友碰到一个变量就问你,“哎,这是啥意思?”)。下面的例子会仔细说一下。


再来一个例子

使用手动Timer的另一个好处是可以在多种情况下使用相同的Timer变量。我经常在游戏中使用一个名为actionDur(动作持续时间)的变量来确定任何一个角色动作可以执行多长时间。假设一个角色有两个动作,攻击和前冲,两者都是依赖于Timer的。在Timer持续时间内,角色被锁定在某一动作中。你也可以使用两个计时器来管理它,比如attackDur和dashDur。或者你可以使用单个计时器,并在两个地方使用它。咱们看看下面的例子。

复用Timer

//Create event
actionDurMax = 60;//这里没有像上面的例子中继续使用数字了,注意变量名
actionDur = actionDurMax;

//Step event
if(attack){
actionDur --;
if(actionDur <= 0){
actionDur = actionDurMax;//重置Timer
attack = false;
}
}

if(dash){
actionDur --;
if(actionDur <= 0){
actionDur = actionDurMax;//重置Timer
dash = false;
}
}

如您所见,两个动作都能够使用相同的计时器变量。请注意,如果您在多个位置使用相同的计时器变量,则每次使用计时器必须完全独立于其他用途。因此,再次使用上面的示例,我必须确保攻击和前冲不能同时为true。如果两个变量同时都是true,那么actionDur会以2倍速倒计时。我强烈建议为你的角色设置状态机,这会让你更方便的管理何时运行的代码。

当然你也可以不用倒计时(正数/倒数都无所谓啦~),稍微修改一下就好。无论您选择正数还是倒数(这里数读三声),这都是个人偏好。

正数Timer

//Create event
actionDur = 0;
actionDurMax = 60;

//Step event
if(attack){
actionDur ++;
if(actionDur >= actionDurMax){
actionDur = 0;//重置Timer
attack = false;
}
}

译注:如果你有点儿困惑,打开手机时钟,一个是计时器,一个是秒表。对,就是它们。

那么,如果您想为多个操作使用单个Timer,但这些操作持续时间有所不同那会怎么样呢?最简单的方法是,如果你使用的是我一直在讨论的相同类型的设置,那就是在动作发生时定义计时器的起点。再次使用攻击操作,让我们看看它是如何工作的。

单个Timer - 但是持续时间不同

//Create event
actionDur = 0;
actionDurMax = 60;

//Step event
if(attack_button)
{
attack = true;
actionDur = 30;//这里作者还是继续使用数字了,建议不要这样做~
}

if(attack)
{
actionDur ++;
if(actionDur >= actionDurMax)
{
actionDur = 0;
attack = false;
}
}

在这个例子中,我们不得不使用一个新的代码块。我们添加了attack_button变量,你可以想象这是一个玩家在游戏中推动攻击按钮。当按下该按钮时,攻击变为真,并且actionDur设置为30.默认情况下,actionDur设置为0,当按下我们的虚拟攻击按钮时,我们会覆盖它。但是,当攻击设置为true时,actionDur仍在累加,然后判断是否达到actionDurMax。只有这一次,不是从0开始,而是从30开始。这实际上减少了我们的攻击行为的持续时间。下面我们再弄的稍微复杂一点儿,我们加上第二个动作

持续时间不同的Timer - 多个动作

//Create event
actionDur = 0;
actionDurMax = 60;

//Step event
if(attack_button){
attack = true;
actionDur = 30;//这里作者还是继续使用数字了,建议不要这样做~
}

if(attack){
actionDur ++;
if(actionDur >= actionDurMax){
actionDur = 0;
attack = false;
}
}

if(dash_button){
dash= true;
actionDur = 10;//这里作者还是继续使用数字了,建议不要这样做~
}

if(dash){
actionDur ++;
if(actionDur >= actionDurMax){
actionDur = 0;
dash = false;
}
}

译注:这里就不详细解释代码含义了,看到这儿的话你肯定已经了解这些东西到底在干嘛了~ 不是么? 

关于自定义Timer,虽然稍微要比Alarm用起来要稍微花些时间来设置,但是这带给我们的好处却更灵活更方便管理自己的代码~ 希望这些内容对你有帮助!感谢你的阅读。

(转发自:原日志地址

近期喜欢的会员

 
顺子 2018-11-09

高产似~哔哔~!

 

加入 indienova

  • 建立个人/工作室档案
  • 建立开发中的游戏档案
  • 关注个人/工作室动态
  • 寻找合作伙伴共同开发
  • 寻求线上发行
  • 更多服务……
登录/注册