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

来源:互联网 发布:推荐好用的精华液知乎 编辑:程序博客网 时间:2024/05/21 09:43
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,bg2end
必须在场景退出的时候删除,否则在场景切换到下一个场景的时候会报一下错误:
 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)


原创粉丝点击