跳转至

流程控制 / Flow

flow 类负责控制代码流程相关的方法。比如延时、异步定时器、周期定时器等。

延时

延时是使用非常频繁的功能之一,延时可以让当前脚本的执行流程中断下来,并且等待指定之间之后再返回。其使用场景广泛用于游戏脚本中需要有延时等待的地方。

我们通过 flow.wait() 来完成延时。其中 ms 参数是延时的时间,单位是毫秒(1 秒 = 1000 毫秒)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
text.show("我不是针对你,我是说在座的各位……", {
  name: "大师兄"
});
text.hide();

// 等待1秒才会继续向下执行
flow.wait(1000);

text.show("都是辣鸡。", {
  name: "大师兄"
});

定时器

例子与演示

我们可以用 flow.setTimeout() 来开始一个定时器,通过定义一个回调方法以及一个超时时间。当设定的时间结束后,这个回调方法会被调用。

需要注意的是,flow.setTimeout()flow.wait() 有所区别。前者方法是不堵塞脚本执行流程的,它会在后台执行,因此定时器回调的时机不受控,需要谨慎使用。

异步定时器可以在不堵塞游戏流程的情况下触发定时行为,通常我们会启动一个异步行为去做一些和游戏主流程无关的动作,比如说发送网络请求、或者更新一个组件、执行一些需要等待但不需要关心实时结果的计算。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 2.5s 后通过 HTML 组件显示一行文本
flow.setTimeout("t", () => {
  widget.html("label", `<div class="text">午时已到!——</div>`, ".text { color: white; }");
}, 2500);

character.show("latyas", "latyas-normal.png", {
  renderer: {
    position: "(center, 80%)"
  }
});

text.show(
  [
    "「异步定时器可以在不堵塞游戏流程的情况下触发定时行为。」",
    "「通常我们会启动一个异步行为去做一些和游戏主进程无关的动作,比如说发送网络请求、或者更新一个组件」"
  ],
  { name: "拉铁丝" }
);

text.hide();

// 最后清理定时器
flow.clearTimeout("t");

如果我们出于某种原因需要清除掉一个异步定时器,可以通过 flow.clearTimeout(id) 完成。在异步定时器还没有启动之前,我们可以把它清掉。清掉后的定时器即便超时了也不会执行。

1
2
3
4
5
6
7
flow.setTimeout("t", () => {
  // 以下内容永远不会执行
  text.show("永远不会执行~");
}, 5000);

// 直接销毁定时器
flow.clearTimeout("t");

周期定时器

周期定时器 可以周期性地无限次执行某些动作。通过 flow.setInterval() 创建,它的使用方法和 flow.setTimeout() 一致,但结果不同。

下面的例子我们创建一个计时器,每 100 毫秒渲染一次 HTML 组件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let sum = 0;

// 我们执行一个周期定时器,时间间隔为 100 毫秒,每毫秒递增 1
// 注:同样名称为 "label" 的 HTML 组件同一时间存在一个,所以即使重新创建,也只是重新渲染 更改 HTML 组件,而不是重复创建一个新的,因此不必担心重复问题

flow.setInterval("t", () => {
  sum ++;
  widget.html("label", `<div class="text">当前计数——${sum}</div>`, ".text { color: white; }");
}, 100);

// 等待 6 秒后自动清除周期定时器
flow.wait(6000)
flow.clearInterval("t");

需要注意的是,周期定时器只要不手动清除,将永远执行下去。


为什么不直接使用 JavaScript 原生的 setTimeout() 和 setInterval() ?

flow.setTimeout() / flow.setInterval() 的调用机制和 JavaScript 中的完全一致。在 AVGPlus 中 只能使用 flow.setTimeout() / flow.setInterval(), 并要求用户传入一个唯一 ID 值,用于标识对应的定时器。

在 JavaScript 中,定时器一旦执行,返回的上下文对象意味着将无法受到脚本引擎的接管,会导致后面进行资源清理或重置引擎状态时无法彻底清除定时器,从而无法进行及时的清理工作。

因此,使用 AVGPlus 提供的代替方法, 不仅可以随时通过您所赋予的 id 对指定的定时器进行手动清理,也方便引擎对定时器进行接管,在游戏结束时自动帮您清理残留的定时器。