time:2015/05/14
描述
lua下使用node的pause函数想暂停layer上的所有动画,结果没有效果
1. pause函数
(1)cc.Node:pause
代码:
void Node ::pause () { _scheduler-> pauseTarget(this ); _actionManager-> pauseTarget(this ); _eventDispatcher-> pauseEventListenersForTarget(this ); }
分析:
* 暂停三个内容:定时器Schedule(其实也是全局的)、actionManager管理的所有动画、事件触发器
* 这里要理解一下三个暂停的原理是什么?
1)Schedule暂停的原理
* 找两个hash表_hashForTimers和_hashForUpdates看有没有我的这个定时器,有的话标记为paused=ture,那么在update函数的时候,就不会调用定时器的回调函数,以实现暂停
2)actionManager暂停原理
* 也是找ActionManager类的成员变量_targets,也是一个hash表。然后检测当前的Node是不是在这个hash表里面,如果在也标记paused为true,在update函数的不执行update函数实现暂停。注意一点,后面有用:就是action默认都是和一个Node绑定的
3)event的暂停原理
* 也是找节点Node所在的hash表,同上面其实也是一样的
(2)cc.Director:pause
代码:
分析:
* 只是把_paused标记为true
* _paused是在drawScene函数中不执行定时器和事件的函数,所以这个结果就是所有的定时器和事件触发器都暂停了,因为都没有执行函数了,但是所有动作还是继续执行!
(3)自己执行pause
* 自己写个for循环,暂停所有的节点
for k, v in pairs(layer:getChildren()) do v:pause() end
2. Lua的pause函数为什么没有起作用?
分析:
* 仔细看代码pause函数,发现只会暂停当前节点的动作,看ActionManager就可以看到,没有遍历所有的子节点
* 定时器和触发事件暂停也只是跟自己有关,即调用没pause函数的那个Node,其他的依旧没有影响,但是因为这两个都是全局的,或者说跟调用的layer没有关系,所以也是没有效果
3. 测试代码(自己记录)
--test [email protected]/04/15 : pause local moveBy = cc.MoveBy:create(2, cc.p(100, 0)) local actionMove = cc.Sequence:create(moveBy, moveBy:reverse()); layer:runAction(cc.RepeatForever:create(actionMove)) local btnPause = cc.MenuItemImage:create("Images/pauseBtn.png","Images/pauseBtn.png"); btnPause:setScale(3) local bPaused = false; local call = function(sender) if not bPaused then bPaused = true; layer:pause(); print("pause ... ") else bPaused = false; layer:resume(); print("resume ... ") end end -- btnPause:addTouchEventListener(call) btnPause:registerScriptTapHandler(call) local menu = cc.Menu:create() menu:setPosition(cc.p(0, 0)) menu:addChild(btnPause) layer:addChild(menu) --schedule -- local fnActionPause = function(dt) layer.fnActionPause = function(dt) print("fnActionPause ... ", dt) local sprite = cc.Sprite:create("Images/CyanTriangle.png") local act = cc.DelayTime:create(2) layer:addChild(sprite) sprite:setPosition(VisibleRect:center()) local callRemove = function() sprite:removeFromParent(true) end sprite:runAction(cc.Sequence:create(act, cc.CallFunc:create(callRemove))) end local scheduler = cc.Director:getInstance():getScheduler(); _schedule = scheduler:scheduleScriptFunc(layer.fnActionPause, 3, false) --test end
4. lua和c++接口的区别
(1)c++
* c++增加定时器或者事件回调函数,不管是selector还是c++ 11中的std::function,都需要保存回调函数的类对象target
* 拿定时器来说Scheduler::schedule():会把事件加到类的成员变量_hashForTimers中,pauseTarget函数就会处理该结构
void Scheduler::schedule(const ccSchedulerFunc& callback, void *target, float interval, unsigned int repeat, float delay, bool paused, const std::string& key) { CCASSERT(target, "Argument target must be non-nullptr"); CCASSERT(!key.empty(), "key should not be empty!"); tHashTimerEntry *element = nullptr; HASH_FIND_PTR(_hashForTimers, &target, element); if (! element) { element = (tHashTimerEntry *)calloc(sizeof(*element), 1); element->target = target; HASH_ADD_PTR(_hashForTimers, target, element); // Is this the 1st element ? Then set the pause level to all the selectors of this target element->paused = paused; } //下面的省略掉...}
(2)lua
* lua添加事件的注册函数为Scheduler::scheduleScriptFunc
*会把事件回调函数以句柄的方式存放在另外一个结构:_scriptHandlerEntries中
* 结构_scriptHandlerEntries只有在Scheduler::update函数中同_hashForTimers一样的处理
*但是!没有pause函数会处理这个结构!!!--->所以理论上lua的事件是没有这个层级上的暂停的(paused=true);
总结
(1)node的pause函数并没有想像中的会暂停layer上的所有children
(2)lua和c++下依旧是有区别的,就是target对象。在c++中会保存回调函数的target对象,但是在lua中只是保存了一个句柄
(3)要想在lua下暂停一个layer下的node,自己循环