译文|GAMEMAKER STUDIO 系列:Timer

作者:highway★
2018-11-26
10 4 4

依旧面向新手

译注:非完全翻译,有些片汤儿话就不翻了,只翻重点 :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 持续时间内,角色被锁定在某一动作中。你也可以使用两个计时器来管理它,比如 attackDurdashDur。或者你可以使用单个计时器,并在两个地方使用它。咱们看看下面的例子。

复用 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 用起来要稍微花些时间来设置,但是这带给我们的好处却更灵活更方便管理自己的代码~ 希望这些内容对你有帮助!感谢你的阅读。

本文为用户投稿,不代表 indienova 观点。

近期点赞的会员

 分享这篇文章

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

参与此文章的讨论

  1. L_eve 2018-11-26

    可以再详细说一下关于变量不要用数字是为什么啊,我刚入门,如果我在后面为自己的数字加备注的话会不会更好

    • highway★ 2018-11-26

      @L_eve:如果过一段时间回过头看代码,要是都是数字,不方便阅读吧~ 注释上还好,我也是入门~ 可能说的不对

    • L_eve 2018-11-27

      @highway★:那我大致明白你的意思了,为了方便以后读取和整理最好是用变量或者在后面注释,无论对自己还是合作的别人读取代码会更方便,了解!

    • 顺子 2018-11-27

      @L_eve:我觉得不要用数字还有一层就是,如果直接写数字日后要修改这个计数的时候就要挨个找挨个儿改了,如果用变量控制,只要去改那个变量就好了

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

登录/注册