您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x 3.x lua中的定时器

2017-07-05 11:21 381 查看
Cocos2dx 3.x Lua 中使用定时器有两种方式:

    (1)self:scheduleUpdateWithPriorityLua(update, priority)

        > 参数一:刷新函数

        > 参数二:刷新优先级

        其中 self 为 Node类 的子类。

        该方法默认为每帧都刷新一次,无法自定义刷新时间间隔。

    (2)scheduler:scheduleScriptFunc(update, inteval, false)

        > 参数一:刷新函数

        > 参数二:每次刷新的时间间隔

        > 参数三:是否只执行一次。false为无限次。

        其中 scheduler 为定时器管理:cc.Director:getInstance():getScheduler()

    推荐使用第二种方式,因为比较通用。

在 引擎根目录/cocos/scripting/lua-bindings/script 的extern.lua文件中定义了 schedule 和 performWithDelay 两个函数:

function schedule(node, callback, delay)
    local delay = cc.DelayTime:create(delay)
    local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback))
    local action = cc.RepeatForever:create(sequence)
    node:runAction(action)
    return action
end

function performWithDelay(node, callback, delay)
    local delay = cc.DelayTime:create(delay)
    local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback))
    node:runAction(sequence)
    return sequence
end

不难看出,这2个函数其实是用Action来实现了循环定时器和一次性回调定时器,按照这个思路也可以自己实现有限次调用的定时器
小结:以上方法提供的定时器是和Node相关的,因此当Node被移除出场景或者其他情况下,这类回调定时器将会被取消

如果要用到独立于Node的定时器,那么就要是用Scheduler的定时器函数了,
在引擎根目录/cocos/scripting/lua-bindings/manual的lua_cocos2dx_manual.cpp文件中定义了scheduleScriptFunc和unscheduleScriptEntry两个函数,分别用来加入和删除定时器:

例子代码如下:

local callbackEntry =nil
local function callback(dt)
  cclog("callback")
  cc.Director:getInstance():getScheduler():unscheduleScriptEntry(callbackEntry)
end

callbackEntry = cc.Director:getInstance():getScheduler():scheduleScriptFunc(callback, 3, false)

其中scheduleScriptFunc的 scheduleScriptFunc)是返回值是一个定时器凭据,该凭据用于在需要删除对应的定时器时传入作为参数,正如上面的例子代码所示。

注意:定义的定时器,必须要删除,实例代码实现背景的滚动

滚动背景:
function SyMapScene:createBg()
local bg = cc.Sprite:create("map.png")
bg:setAnchorPoint(0,0)
bg:setPosition(0,0)

local bg2 = cc.Sprite:create("map.png")
bg2:setAnchorPoint(0,0)
bg2:setPosition(0, bg:getContentSize().height - 2)

local function bgMove()

bg:setPositionY(bg:getPositionY() - 1)
bg2:setPositionY(bg2:getPositionY() - 1)

if (bg:getPositionY() < - bg:getContentSize().height) then

bg:setPositionY(bg2:getPositionY() + bg2:getContentSize().height)

elseif (bg2:getPositionY() <- bg2:getContentSize().height) then

bg2:setPositionY(bg:getPositionY() + bg:getContentSize().height)
end

end
schedulerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(bgMove, 0, false)

return bg,bg2
end
必须在场景退出的时候删除,否则在场景切换到下一个场景的时候会报一下错误:

 LUA ERROR: [string "SyMap.lua"]:37: invalid 'cobj' in function 'lua_cocos2dx_Node_getPositionY'

这是一个类似于空指针的错误,Node已经手动死亡之后依然会调用Node,定时调用依旧在生效即在调用。

场景退出的时候取消调用;
function SyMapScene:onExit()
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(schedulerID)
end


或者直接使用第一种调用方式:

 self:scheduleUpdateWithPriorityLua(bgMove,0)

不必手动删除schedule的调用,在场景切换到下一个场景的时候不会报错。

二:关于 invalid 'cobj' in function 错误:

这是因为对一个Node调用其函数时其已经被GC了。

首先尝试手动控制Node的生命周期:

littleMonsterBullet:retain() 

littleMonsterBullet:release() 

发现无效,原来有一个定时器在定时调用一个函数对Node进行处理:
littleMonsterBullet.schedulerID =cc.Director:getInstance():getScheduler():scheduleScriptFunc(tick_attack_hero,0, false)

Node已经手动死亡之后依然会调用Node

于是调用:littleMonsterBullet:unscheduleUpdate()
但是发现不是使用self:scheduleUpdateWithPriorityLua(update,priority)添加的schedule,这样unschedule是无效的。

最后只能:
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(littleMonsterBullet.schedulerID)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: