饥荒联机版mod制作[事件发送与监听、事务的延时执行与循环执行]

为了能更好的完成实体的交互与新玩法的开发,我们经常需要用到下面的技巧:

发送事件:inst:PushEvent("event_name",data)

监听事件:inst:ListenForEvent("event_name",fn(inst,data)

延时执行:inst:DoTaskInTime(time,fn(),data)

循环执行:inst:DoPeriodicTask(time,fn(),data)

一、事件的发送与监听

1.1  推送事件:PushEvent

事件的推送与监听分为实体内推送与世界内推送。

1.1.1  实体内推送事件:inst:PushEvent

在实体内推送的时间只有本实体能接收到,同一个实体可以同时推送多个不同名字的事件,此时如果有其他实体推送的事件与本实体推送的事件的名字相同,也不会有任何影响。

也就是说,各个实体间的事件相互独立,同一实体内的不同事件相互独立。

inst:PushEvent("event_name",data1,data2,...)
-- 第一个位置的参数为事件名称
-- 之后所有位置均为向“ListenForEvent("event_name",fn(inst,data))”中表“data”推送的参数,存放在data.data1、data.data2...

1.1.2  世界中推送事件:

在世界内推送的事件所有实体都可以接收到,且同一名字的事件会发生覆盖。具体用法与实体内推送事件相同:

TheWorld:PushEvent("event_name",data1,data2,...)

1.2  监听事件:ListenForEvent

监听事件需要与推送事件配套使用,相当于远程传递参数的便捷方法。

inst:ListenForEvent("event_name",fn(inst,data)
-- 第一个位置为监听的事件名字
-- 第二个位置为监听到事件后需要执行的函数,向内传递的两个参数是inst(监听者)与data(PushEvent传来的表)

1.3  事件的进阶运用:timer组件

timer组件是用来计时的组件,通过下面语句即可添加到实体:

inst:Addcomponent("timer")

timer通过发送事件和监听事件来完成“时间到”的回调:

1.3.1  开始计时

开始计时的代码为:

inst.components.timer:StartTimer("timer_name",time,paused,initialtime_override)
-- 第一个参数为计时器名称,后面在监听计时器结束时会用到
-- 第二个参数为计时时间
-- 第三个参数为延迟计时时间
-- 第四个参数为覆盖计时时间time

后两个参数为可选参数。 

initialtime_override相当于一个判断语句,如果传入则覆盖,如果没传入则继续使用time。

StartTimer的定义如下:

function Timer:StartTimer(name, time, paused, initialtime_override)
    if self:TimerExists(name) then
        print("A timer with the name ", name, " already exists on ", self.inst, "!")
        return
    end

    self.timers[name] =
    {
        timer = self.inst:DoTaskInTime(time, OnTimerDone, self, name),
        timeleft = time,
        end_time = GetTime() + time,
        initial_time = initialtime_override or time,
        paused = false,
    }

    if paused then
        self:PauseTimer(name)
    end
end

1.3.2  暂停计时

暂停计时的代码为:

inst.components.timer:PauseTimer("timer_name")
-- 暂停计时器“timer_name”

1.3.3  恢复计时

恢复计时的代码为:

inst.components.timer:ResumeTimer("timer_name")
-- 恢复计时器“timer_name”

1.3.4  计时时间到

在timer组件的定义中,计时时间到是通过推送事件来通知的,其代码如下:

local function OnTimerDone(inst, self, name)
    self:StopTimer(name)
    inst:PushEvent("timerdone", { name = name })
end

其中调用的StopTimer()如下:

function Timer:StopTimer(name)
    if not self:TimerExists(name) then
        return
    end

    if self.timers[name].timer ~= nil then
        self.timers[name].timer:Cancel()
        self.timers[name].timer = nil
    end
    self.timers[name] = nil
end

通过监听事件,我们可以获知计时时间到的消息,再通过推送事件中传递的参数判断是哪一个计时器结束,我们就可以利用计时器完成一些工作。

监听计时结束的代码如下:

inst:ListenForEvent("timerdone", function(inst, data)
    -- 你的代码
end)
-- 注意区分这里function传递下来的inst与原inst的区别。当这是在实体内推送的事件(比如现在使用的timer组件)时,二者没有区别;当这是世界事件是,二者可能会不同

二、执行事务

2.1  延时执行事务

通过延时执行事务,我们可以完成:

多样化游戏内容(随机推迟任务执行时间)

有序化任务(设置不同的推迟时间)

等。

推迟执行事务的 代码如下:

inst:DoTaskInTime(time, fn, data1,data2,...),
-- 第一个位置为延迟时间
-- 第二个位置为推迟时间后执行的函数
-- 其余位置为传递的参数

以前面提到的timer组件中计时时间到函数为例:

local function OnTimerDone(inst, self, name)  --  注意这里接收的参数
    self:StopTimer(name)
    inst:PushEvent("timerdone", { name = name })
end

function Timer:StartTimer(name, time, paused, initialtime_override)
    if self:TimerExists(name) then
        print("A timer with the name ", name, " already exists on ", self.inst, "!")
        return
    end

    self.timers[name] =
    {
        timer = self.inst:DoTaskInTime(time, OnTimerDone, self, name),  -- 延时执行
        timeleft = time,
        end_time = GetTime() + time,
        initial_time = initialtime_override or time,
        paused = false,
    }

    if paused then
        self:PauseTimer(name)
    end
end

这里inst:DoTaskInTime(time, OnTimerDone, self, name)向函数OnTimerDone中传递了两个参数,但OnTimerDone(inst, self, name)中接收了三个参数,这是因为DoTaskInTime默认吧inst传进函数内。

2.2  重复执行事务

物品的实体预制件函数fn()只会在每个实体初始化时执行之后若无调用则不会执行我们写在其中的逻辑的。这时我们可以利用重复执行事务语句,通过不断重复执行我们安置在fn()中的代码,加上一些条件语句,即可在我们需要他们的时候发挥作用。这就是我们所说的“刷帧”。

重复执行事务的代码如下:

inst:DoPeriodicTask(time, function()
-- 你的代码,一般不会长时间重复执行某一动作,所以常常与条件语句结合,判断时机恰当时再执行
end)

这里直接将执行的事务函数写在了DoPeriodicTask语句内,为了使fn()代码简洁,我们可以将其转移至fn()外:

local function on_doing_task(inst,...)
{
    -- 代码
}




inst:DoPeriodicTask(time,on_doing_task(inst,...))

其中的time为每隔time秒执行一次任务,故time=1时,每1s执行一次任务;也可以用宏定义帧:FRAMES

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值