1、Action类继承关系图,虽然这张图是2.X的版本,以为没找到3.X的这种图,
但是整体来说是一样的,CCFiniteTimeAction又分为CCActionInstanse(瞬时动作的基类)和CCActionInterval(延时动作的基类)
2、
动作管理类分析:
动作管理类,我们一般不需要直接使用,如果要是使用摸个动作,直接使用Node中的方法即可。
3、整个动作的管理,跟下面这个结构密不可分
//
// singleton stuff
//
typedef struct _hashElement
{
struct _ccArray *actions; //一个Node上,可能又很多个action
Node *target; //Node
int actionIndex;
Action *currentAction; //当前的Action
bool currentActionSalvaged; //是否被标记
bool paused; //是否暂停
UT_hash_handle hh; //hashTable
} tHashElement;
4、
// main loop
//这个update方法在每次循环的时候都会被调用,所有动作的执行处理,都是在这个函数中。
void ActionManager::update(float dt)
{
for (tHashElement *elt = _targets; elt != nullptr; )
{
_currentTarget = elt;
_currentTargetSalvaged = false;
if (! _currentTarget->paused)
{
// The 'actions' MutableArray may change while inside this loop.
//这里循环Node的所有Action,因为一个Node可能又很多个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的step方法,这个方法会被继承自Action的具体动作类重写,
如:(1)ActionInterval是有一段持续时间的动作
void ActionInterval::step(float dt)
{
if (_firstTick)
{
_firstTick = false;
_elapsed = 0;
}
else
{
_elapsed += dt;
}
//这里调用update方法,更新动作,如MoveTo,需要更新坐标,位置等等
this->update(MAX (0, // needed for rewind. elapsed could be negative
MIN(1, _elapsed /
MAX(_duration, FLT_EPSILON) // division by 0
)
)
);
}
(2)
ActionInstant是立即执行的动作,这里就直接调用update
void ActionInstant::step(float dt) {
CC_UNUSED_PARAM(dt);
update(1);
}
_currentTarget->currentAction->step(dt);
if (_currentTarget->currentActionSalvaged)
{
// 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
//判断是否结束,如果结束,就stop,并且从Node的Action数组中移除。
if (_currentTarget->currentAction->isDone())
{
_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)
if (_currentTargetSalvaged && _currentTarget->actions->num == 0)
{
deleteHashElement(_currentTarget);
}
}
// issue #635
_currentTarget = nullptr;
}