Cocos2d-x 3.X里面的调度器和update()

Cocos2d-x 3.X里有三种调度器,分别为默认调度器scheduleUpdate(), 自定义调度器schedule(), 和单次调度器scheduleOnce()。它们都是Node类成员函数。它们又都分别调用了单例模式的Scheduler类里面对应的三个调度器。所以我们既可以通过Node里面的调度器来定时调度某个事件,也可以直接通过总调度器Scheduler来调度事件。但是要注意两者的参数(调度对象)不同。

例如,如果某个Node子类(如图层,精灵等)对象调用的是Node里面的scheduleUpdate()(没有参数),它首先会去调度子类中的update()函数,如果子类中没有update(),它就会调度Node里面的update()函数:

CCNode.cpp

// override me
void Node::update(float fDelta)
{
#if CC_ENABLE_SCRIPT_BINDING
    if (0 != _updateScriptHandler)
    {
        //only lua use
        SchedulerScriptData data(_updateScriptHandler,fDelta);
        ScriptEvent event(kScheduleEvent,&data);
        ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
    }
#endif
    
    if (_componentContainer && !_componentContainer->isEmpty())
    {
        _componentContainer->visit(fDelta);
    }
}

在这里面我们看到它调用了componentContainer。控制器ComController里面的update()就是在这里被调用的。但是(第二遍),如果update()被子类重写,那么子类对象调度的就是子类的update()函数,同时ComController里面的update()就不再被调用,除非把这部分也重写进去,这一点要非常注意。

如果我们直接调用Scheduler里面的scheduleUpdate(T* target, int priority, bool paused),那么必须指定调度对象,它会启动指定对象中的update()函数。

在这里顺便提一下面向对象编程时要注意的地方:父类对象只能调用父类函数,子类对象调用(即使是通过父类函数间接调用)的首先是子类函数,除非子类中没有定义才去调用父类函数。在上面这个例子中某个子类对象先调用了父类Node里面的scheduleUpate()函数(子类也可以重写该函数),而该函数又可以调用子类中重写的update()函数(此时update必须为虚函数,否则在父类中就找不到声明了)(第三遍)。

父类中的纯虚函数只能被子类对象调用,只不过当我们把子类对象的类型转化为父类类型时,该对象仍然可以调用子类中定义的(父类中声明的)纯虚函数,但是它本质上还是子类对象(从内存分配来看)。


在使用scheduleUpdate()时要注意两个问题:

1)怎么调用调度器

scheduleUpdate()可以在某个场景或图层中直接手动调用。但是注意如果在使用ComController时,以下两个函数也会自动调用该调度器:

CCNode.cpp

bool Node::addComponent(Component *component)
{
    // lazy alloc
    if (!_componentContainer)
        _componentContainer = new (std::nothrow) ComponentContainer(this);
    
    // should enable schedule update, then all components can receive this call back
    scheduleUpdate();
    
    return _componentContainer->add(component);
}

CCComController.cpp
void ComController::onEnter()
{
    if (_owner != nullptr)
    {
        _owner->scheduleUpdate();
    }
}

2)调度哪个update()

前面已经提到过,要注意调度的是Node子类(如图层,精灵等)中的update()还是ComController里面的update()(通过Node中update()调用)。



水平有限,如有不妥,欢迎拍砖!

你可能感兴趣的:(cocos2d-x,C++)