Cocos2d-x 学习笔记(8) ActionManager
1. 概述
ActionManager管理所有的action,调度所有的action,删除指定的action。每个action对应一个node对象,action存储在actions中,actions和node绑定在一个element中。
2. 学习
2.1 在哪使用
Director类中有成员ActionManager类单例对象指针_actionManager。
Director类在创建时调用到Director::init(void)方法,有以下操作:
_actionManager = new (std::nothrow) ActionManager(); _scheduler->scheduleUpdate(_actionManager, Scheduler::PRIORITY_SYSTEM, false);
scheduleUpdate方法是执行了schedulePerFrame方法,_actionManager的update方法作为回调函数,故该update方法在每帧被调用。
schedulePerFrame方法执行后,_actionManager作为target,update方法作为回调函数新建优先级最高的Timer。
2.2 一些成员
ActionManager类成员变量:
struct _hashElement *_targets; // Element容器
struct _hashElement *_currentTarget; // 当前的Element
bool _currentTargetSalvaged;
ActionManager类结构体变量:
typedef struct _hashElement
{
struct _ccArray *actions;
Node *target;
int actionIndex;
Action *currentAction; // 当前Action
bool currentActionSalvaged;
bool paused;
UT_hash_handle hh;
} tHashElement;
2.3 update方法
简要的说,update方法是对哈希链表_targets的每个element作为_currentTarget,再把每个element的action作为currentAction,其中包含对action和element的延后release()。
ActionManager的update(float dt)方法执行大致流程:
2.4 addAction方法
addAction(Action *action, Node *target, bool paused)方法执行流程:
新建element时,会对target执行retain()。
action添加到actions时,执行ccArrayAppendObject(element->actions, action),对action执行retain()。
2.5 pause resume
pauseTarget(Node *target) resumeTarget(Node *target) resumeTargets(const Vector<Node*>& targetsToResume)
上面这3个方法对target对应的element的paused变量置true或false。
pauseAllRunningActions()方法,对哈希链表_targets的每个element的成员pause置true,并用Vector<Node*> idsWithActions保存暂停了的target。添加到容器时,这些target执行retain(),在手动调用恢复方法resumeTargets(const Vector<Node*>& targetsToResume)后,对Vector容器执行clear()方法,此时对target执行release()。
2.6 remove
删除action操作归纳到以下两种方法:
removeAllActionsFromTarget(Node *target)
removeActionAtIndex(ssize_t index, tHashElement *element)
removeAllActionsFromTarget方法
首先通过target从哈希链表_targets中查找对应的element。如果是element的currentAction且currentActionSalvaged为false,说明该action被target执行,对于这个action要retain(),并currentActionSalvaged置true,下一步的release()延后执行。再执行ccArrayRemoveObjectAtIndex,所有action执行release(),之后只有currentAction没被删除。actions为空就要删除element了,此时若_currentTarget为当前element,即target正在执行,_currentTargetSalvaged置true,暂不删除element。
removeActionAtIndex方法
从element的actions中对指定的action执行release(),若currentAction为当前action则延后release(),并修改标志currentActionSalvaged为true。之后若actions为空,在删除element之前,若_currentTarget为当前element,_currentTargetSalvaged置true并暂不删除。
2.7 currentActionSalvaged _currentTargetSalvaged
currentActionSalvaged属于element,_currentTargetSalvaged属于ActionManager。
在ActionManager的update方法中,在对当前遍历到的element进行所有操作之前,_currentTargetSalvaged置false,在对element的actions遍历结束后,判断_currentTargetSalvaged。若在遍历actions时,有action被remove操作,之后需要判断actions是否为空,为空则置_currentTargetSalvaged为true。即在对element的actions遍历结束后才能对release()无action的element。
在对action执行step(dt)之前,currentActionSalvaged置false,执行step(dt)结束之后,再判断currentActionSalvaged,即对removeAction方法指定的action执行release()需要在step(dt)执行之后真正执行。