• cocos2dx中node的pause函数(lua)


    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 page@2015/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,自己循环
  • 相关阅读:
    win32下使用相对exe文件的绝对路径资源
    修改Unity中Lua文件的默认打开程序
    Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题
    Unity3D MonoBehaviour的生命周期(lifecycle)
    使用Doxygen + graphviz生成Unity 3d的UGUI类图
    IEEE 754二进制浮点数算术标准
    foxmail同步QQ邮箱里的所有文件夹
    Windows下的搜索神器 —— everything
    electron实现类似QQ来新消息时的闪烁与任务栏窗口提醒
    iOS 10.3下使用Fiddler抓取HTTPS请求
  • 原文地址:https://www.cnblogs.com/pk-run/p/4441295.html
Copyright © 2020-2023  润新知