马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 _何度 于 2020-11-19 13:30 编辑
lua实现的 计时器系统,就是通常意义的中心计时器,通过对一个 jass的Timer计时器的管理 来虚拟出任意数量的计时器。 基于以下理由,我模拟了这个模块 1.魔兽没有开源,yd源码中也没有 jass计时器的实现,这是一个黑箱。 2.jass计时器 用起来并不顺手,Timer对象占用的资源不理解为什么那么大。 3.jass计时器是多线程实现的,在我的项目中引发了异步问题。
调用接口保留了jass计时器的写法。 用法简介: 1.创建计时器 local New_Timer=CreateTimer() 2.运行计时器(可选择指定计时器 或用一个匿名计时器) Timer(timeout 到期时间, periodic 是否循环, whichTimer 指定的计时器(可不选) ) ( --执行函数 function()
end, --结束条件 function() return 条件表达式 end ) 用例: Timer(0.5,true,self.LastTimer)
(
function()
total_past=total_past+0.5
--单位添加引导特效
if self.buff_factory then
if self.auto_color then
self.Lk_color=RandomPick(Ability_link.Colors,true)
end
for _,hero in ipairs(self.attach_hero) do
local target=hero
local last=0.6
local compose_type='cover_time'
local model=self.auto_color and table.concat{'abilityEffect\\LXTX\\',self.Lk_color,'.mdx'} or ''
local buff=self.buff_factory(target,last,compose_type,model)
Buff_add(buff)
end
end
if total_past>=self.last then
self:End_Define()
end
end,
function()
return total_past>=self.last
end
)
实现: --====================require==========================================
local OldCreateTimer=CJ.CreateTimer
local OldTimerStart=CJ.TimerStart
--=====================================================================
local AtomTimer={}
local mt={}
AtomTimer.__index=mt
mt.timeout=-1 --计时器周期
mt.trigleft=-1 --触发剩余时间
mt.periodic=false --是否循环
mt.condition=nil --循环的停止条件
mt.id=nil --计时器标识id
mt.pause=false --是否暂停
mt.func=nil --执行函数
mt.removed=false --是被移除
local TimerEventList={} --中心计时器事件列表
local ExpiredTimer=nil --到期的计时器【AtomTimer 类型】
local GameFrames=0.03 --游戏帧数
local GameTimePast=0 --游戏逝去时间
CenterTimer={} --中心计时器对象
CenterTimer.handle=OldCreateTimer() --中心计时器jass对象
CenterTimer.Frames=GameFrames --中心计时器帧数
CenterTimer.ETimerNum=0 --当前有效计时器个数
CenterTimer.runing=false --是否正在运行
CenterTimer.AtomId=0 --分发的AtomTimerId
CenterTimer.AllTimerList={} --所有分发的AtomTimer记录
CenterTimer.Start=function() --运行中心计时器
OldTimerStart(CenterTimer.handle,CenterTimer.Frames,true,function()
GameTimePast=GameTimePast+GameFrames
if #TimerEventList <=0 then
return
else
--print('事件列表长度',#TimerEventList,'运行计时器数目',CenterTimer.ETimerNum)
for index=1,#TimerEventList do
--print(index,TimerEventList[index])
if TimerEventList[index] and not TimerEventList[index].pause then
TimerEventList[index].trigleft=TimerEventList[index].trigleft-GameFrames
if TimerEventList[index].removed then error('计时器移除异常') end
if TimerEventList[index].trigleft<=0 then
ExpiredTimer=TimerEventList[index]
xpcall(ExpiredTimer.func, function(e) print(debug.traceback()) print('中心计时器-执行函数异常') return e end)
if not ExpiredTimer.periodic then
ExpiredTimer.removed=true
CenterTimer.ETimerNum=CenterTimer.ETimerNum-1
else
ExpiredTimer.trigleft=ExpiredTimer.timeout
if ExpiredTimer.condition and ExpiredTimer.condition() then
ExpiredTimer.removed=true
CenterTimer.ETimerNum=CenterTimer.ETimerNum-1
end
end
end
end
end
for index=#TimerEventList,1,-1 do
if TimerEventList[index].removed then
table.remove(TimerEventList,index)
end
end
end
end)
end
function os.clock() --获取当前游戏时间
return GameTimePast
end
local CTlock=false --创建计时器进程锁
function CreateTimer(provideId) --分配一个计时器对象
if not CTlock then CTlock=true
else
for i=1,8 do
for j=1,6 do
CJ.DisplayTimedTextToPlayer(CJ.Player(i-1),0,0,120,'|cFFF00000[错误]:创建计时器进程冲突!!')
end
end
return error('创建计时器进程冲突!!')
end
if not provideId then
CenterTimer.AtomId=CenterTimer.AtomId+1
provideId=CenterTimer.AtomId
end
local atomtimer={id=provideId}
setmetatable(atomtimer,AtomTimer)
CenterTimer.ETimerNum=CenterTimer.ETimerNum+1
CTlock=false
return atomtimer
end
--运行计时器
---@param timeout integer 周期
---@param periodic boolean 是否循环
---@param whichtimer table 自定义计时器 AtomTimer 对象
---@return table
function Timer(timeout,periodic,whichtimer)
return function(callback,condition)
local timer=whichtimer or CreateTimer()
timer.timeout=timeout
timer.trigleft=timeout
timer.periodic=periodic
timer.func=callback
timer.condition=condition
timer.pause=false
timer.removed=false
for index,atomtimer in ipairs(TimerEventList) do
if atomtimer.id==timer.id then
TimerEventList[index]=timer
return timer
end
end
table.insert(TimerEventList,timer)
return timer
end
end
function DestroyTimer(timer) --删除计时器
if Is_intable(TimerEventList,timer) then
timer.removed=true
TableRemoveData(TimerEventList,timer)
CenterTimer.ETimerNum=CenterTimer.ETimerNum-1
end
end
function PauseTimer (timer) --暂停计时器
timer.pause=true
end
function ResumeTimer (timer) --恢复计时器
timer.pause=false
end
function TimerGetRemaining(timer) --获取计时器剩余时间
if not timer.removed then
return timer.trigleft
else
return -1
end
end
function ReCreateTimer(timer)
DestroyTimer(timer)
timer.timeout=-1
timer.trigleft=-1
timer.periodic=false
timer.func=nil
timer.condition=nil
timer.pause=false
timer.removed=false
return timer
end
function GetExpiredTimer() --获取当前到期的计时器
return ExpiredTimer
end
function ExtendTime(whichtimer,ExTime) --延长计时器到期时间
if not whichtimer.removed then
whichtimer.trigleft=whichtimer.trigleft+ExTime
return true
end
return false
end
function ReSetTime(whichtimer,time) --重置计时器到期时间
if not whichtimer.removed then
whichtimer.trigleft=time or whichtimer.timeout
return true
end
return false
end
CenterTimer.Start()
print 'timer.lua'
|