当我们调用runAction的时候,实际上是创建一个Action,并把这个Action交给ActionManager管理,由ActionManager负责更新Action的行为和管理Action的生命周期。
Director在初始化的时候会创建一个ActionManager
_actionManager = new (std::nothrow) ActionManager();
_scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
Node对象在构造的时候,会在自己的成员变量里面保存一个Director的ActionManager的指针
_director = Director::getInstance();
_actionManager = _director->getActionManager();
_actionManager->retain();
当我们调用runAction的时候,就会把action交给ActionManager管理
Action * Node::runAction(Action* action)
{
CCASSERT( action != nullptr, "Argument must be non-nil");
_actionManager->addAction(action, this, !_running);
return action;
}
void ActionManager::addAction(Action *action, Node *target, bool paused)
{
CCASSERT(action != nullptr, "action can't be nullptr!");
CCASSERT(target != nullptr, "target can't be nullptr!");
/*找到target相关的成员*/
tHashElement *element = nullptr;
// we should convert it to Ref*, because we save it as Ref*
Ref *tmp = target;
HASH_FIND_PTR(_targets, &tmp, element);
if (! element)
{
/*没有找到就创建一个*/
element = (tHashElement*)calloc(sizeof(*element), 1);
element->paused = paused;
target->retain();
element->target = target;
HASH_ADD_PTR(_targets, target, element);
}
/*扩展可以容纳的action数量*/
actionAllocWithHashElement(element);
CCASSERT(! ccArrayContainsObject(element->actions, action), "action already be added!");
/*存入新action*/
ccArrayAppendObject(element->actions, action);
action->startWithTarget(target);
}
ActionManager创建的时候,把自己的update函数加入了scheduler,所有ActionManager::update每贞都会被调用,用来更新管理的action行为
_scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
void ActionManager::update(float dt)
{
/*遍历所有的action管理成员,每个node对应一个管理成员,管理node的所有action*/
for (tHashElement *elt = _targets; elt != nullptr; )
{
_currentTarget = elt;
_currentTargetSalvaged = false;
/*如果目标是暂停状态可以不处理*/
if (! _currentTarget->paused)
{
// The 'actions' MutableArray may change while inside this loop.
/*遍历所有的action*/
for (_currentTarget->actionIndex = 0; _currentTarget->actionIndex < _currentTarget->actions->num;
_currentTarget->actionIndex++)
{
_currentTarget->currentAction = (Action*)_currentTarget->actions->arr[_currentTarget->actionIndex];
if (_currentTarget->currentAction == nullptr)
{
continue;
}
_currentTarget->currentActionSalvaged = false;
/*更新action的行为*/
_currentTarget->currentAction->step(dt);
if (_currentTarget->currentActionSalvaged)
{
/*处理执行action的时候,action被删除的情况*/
// The currentAction told the node to remove it. To prevent the action from
// accidentally deallocating itself before finishing its step, we retained
// it. Now that step is done, it's safe to release it.
_currentTarget->currentAction->release();
} else
if (_currentTarget->currentAction->isDone())
{
/*如果action已完成则删除这个action*/
_currentTarget->currentAction->stop();
Action *action = _currentTarget->currentAction;
// Make currentAction nil to prevent removeAction from salvaging it.
_currentTarget->currentAction = nullptr;
removeAction(action);
}
_currentTarget->currentAction = nullptr;
}
}
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
elt = (tHashElement*)(elt->hh.next);
// only delete currentTarget if no actions were scheduled during the cycle (issue #481)
/*如果目标节点已经没有action了,则可以删除这个管理元素,释放内存资源*/
if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
{
deleteHashElement(_currentTarget);
}
}
// issue #635
_currentTarget = nullptr;
}