cocos2d-x动作道理
添加时间:2013-7-1 点击量:
起首CCAction是所有动作的基类,如下图持续关系:
那么来看看CCAction的定义:
class CC_DLL CCAction : public CCObject
{
public:
CCAction(void);
virtual ~CCAction(void);
const char description();
virtual CCObject copyWithZone(CCZone pZone);
//! return true if the action has finished
virtual bool isDone(void);
virtual void startWithTarget(CCNode pTarget);
/
called after the action has finished. It will set the target to nil.
IMPORTANT: You should never call [action stop] manually. Instead, use: target->stopAction(action);
/
virtual void stop(void);
//! called every frame with its delta time. DONT override unless you know what you are doing.
virtual void step(float dt);
virtual void (float time);
inline CCNode getTarget(void) { return m_pTarget; }
inline void setTarget(CCNode pTarget) { m_pTarget = pTarget; }
inline CCNode getOriginalTarget(void) { return m_pOriginalTarget; }
inline void setOriginalTarget(CCNode pOriginalTarget) { m_pOriginalTarget = pOriginalTarget; }
inline int getTag(void) { return m_nTag; }
inline void setTag(int nTag) { m_nTag = nTag; }
public:
static CCAction create();
protected:
CCNode m_pOriginalTarget;
CCNode m_pTarget;
int m_nTag;
};
在类定义最后有三个成员变量,而持续自CCAction的CCFiniteTimeAction首要新增长了一个用于保存该动作总完成时候的成员变量float m_fDuration;
对于其两个子类CCActionInstant和CCActionInterval,前者没有新增任何函数和变量,而后者增长了两个成员变量:float m_elapsed(记录从动作开端起逝去的时候);和bool m_bFirstTick(一个把握变量);
那么动作是如何履行的呢?
当一个节点调用runAction办法时,动作经管类CCActionManager(单例类)会将新的动作和节点添加到其经管的动作表中。
CCAction CCNode::runAction(CCAction action)
{
CCAssert( action != NULL, Argument must be non-nil);
m_pActionManager->addAction(action, this, !m_bRunning);
return action;
}
在addAction中,将动作添加到动作队列后,就会对该动作调用其成员函数startWithTarget(CCNode pTarget)来绑定该动作的履行节点,和初始化动作类的成员变量。
这些工作都完成后,每一帧刷新屏幕时,体系就会在CCActionManager中遍历动作表中的每一个动作,并调用动作的step(float)办法。而step办法首要负责策画m_elapsed的值,并调用(float)办法。
void CCActionInterval::step(float dt)
{
if (m_bFirstTick)
{
m_bFirstTick = false;
m_elapsed = 0;
}
else
{
m_elapsed += dt;
}
this->(MAX (0, // needed for rewind. elapsed could be negative
MIN(1, m_elapsed / MAX(m_fDuration, FLT_EPSILON) // division by 0
)
)
);
}
传入办法的float型参数默示逝去的时候与动作完成须要的时候的比值,介于0-1之间,即动作完成的百分比。然后在办法中,经由过程完成比例对节点的属性进行操纵来达到动作的结果。
例如:对MoveBy调用时,经由过程传入的比例调用setPosition直接批改节点的属性。
最后在每一帧停止后,CCActionManager的会搜检动作队列中每个动作的isDone函数是否返回true,若是返回true,则动作停止,将其从队列中删除。
——————————————————————————————————————————————————————————————————————————
从上方知道:动作都是由CCActionManager来经管。那我们再来看看CCActionManager的工作道理。
在CCDirector初始化时,履行了如下代码:
// scheduler
m_pScheduler = new CCScheduler();
// action manager
m_pActionManager = new CCActionManager();
m_pScheduler->scheduleUpdateForTarget(m_pActionManager, krioritySystem, false);
可见动作经管类在创建时就注册了Update按时器,那么CCScheduler在游戏的每一帧mainLoop更新中都邑触发CCActionManager注册的(float )办法。调剂器道理请参照此链接:http://www.cnblogs.com/songcf/p/3162414.html
// main loop
void CCActionManager::(float dt)
{
//列举措作表中的每一个节点
for (tHashElement elt = m_pTargets; elt != NULL; )
{
m_pCurrentTarget = elt;
m_bCurrentTargetSalvaged = false;
if (! m_pCurrentTarget->paused)
{
//列举节点的每一个动作 actions数组可能会在轮回中被批改
for (m_pCurrentTarget->actionIndex = 0; m_pCurrentTarget->actionIndex < m_pCurrentTarget->actions->num;
m_pCurrentTarget->actionIndex++)
{
m_pCurrentTarget->currentAction = (CCAction)m_pCurrentTarget->actions->arr[m_pCurrentTarget->actionIndex];
if (m_pCurrentTarget->currentAction == NULL)
{
continue;
}
m_pCurrentTarget->currentActionSalvaged = false;
m_pCurrentTarget->currentAction->step(dt);
if (m_pCurrentTarget->currentActionSalvaged)
{
// The currentAction told the node to remove it. To prevent the action
// accidentally deallocating itself before finishing its step, we retained
// it. Now that step is done, its safe to release it.
m_pCurrentTarget->currentAction->release();
} else
if (m_pCurrentTarget->currentAction->isDone())
{
m_pCurrentTarget->currentAction->stop();
CCAction pAction = m_pCurrentTarget->currentAction;
// Make currentAction nil to prevent removeAction salvaging it.
m_pCurrentTarget->currentAction = NULL;
removeAction(pAction);
}
m_pCurrentTarget->currentAction = NULL;
}
}
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
elt = (tHashElement)(elt->hh.next);
// only currentTarget if no actions were scheduled during the cycle (issue #481)
if (m_bCurrentTargetSalvaged && m_pCurrentTarget->actions->num == 0)
{
HashElement(m_pCurrentTarget);
}
}
// issue #635
m_pCurrentTarget = NULL;
}
真正的心灵世界会告诉你根本看不见的东西,这东西需要你付出思想和灵魂的劳动去获取,然后它会照亮你的生命,永远照亮你的生命。——王安忆《小说家的十三堂课》
起首CCAction是所有动作的基类,如下图持续关系:
那么来看看CCAction的定义:
class CC_DLL CCAction : public CCObject
{
public:
CCAction(void);
virtual ~CCAction(void);
const char description();
virtual CCObject copyWithZone(CCZone pZone);
//! return true if the action has finished
virtual bool isDone(void);
virtual void startWithTarget(CCNode pTarget);
/
called after the action has finished. It will set the target to nil.
IMPORTANT: You should never call [action stop] manually. Instead, use: target->stopAction(action);
/
virtual void stop(void);
//! called every frame with its delta time. DONT override unless you know what you are doing.
virtual void step(float dt);
virtual void (float time);
inline CCNode getTarget(void) { return m_pTarget; }
inline void setTarget(CCNode pTarget) { m_pTarget = pTarget; }
inline CCNode getOriginalTarget(void) { return m_pOriginalTarget; }
inline void setOriginalTarget(CCNode pOriginalTarget) { m_pOriginalTarget = pOriginalTarget; }
inline int getTag(void) { return m_nTag; }
inline void setTag(int nTag) { m_nTag = nTag; }
public:
static CCAction create();
protected:
CCNode m_pOriginalTarget;
CCNode m_pTarget;
int m_nTag;
};
在类定义最后有三个成员变量,而持续自CCAction的CCFiniteTimeAction首要新增长了一个用于保存该动作总完成时候的成员变量float m_fDuration;
对于其两个子类CCActionInstant和CCActionInterval,前者没有新增任何函数和变量,而后者增长了两个成员变量:float m_elapsed(记录从动作开端起逝去的时候);和bool m_bFirstTick(一个把握变量);
那么动作是如何履行的呢?
当一个节点调用runAction办法时,动作经管类CCActionManager(单例类)会将新的动作和节点添加到其经管的动作表中。
CCAction CCNode::runAction(CCAction action)
{
CCAssert( action != NULL, Argument must be non-nil);
m_pActionManager->addAction(action, this, !m_bRunning);
return action;
}
在addAction中,将动作添加到动作队列后,就会对该动作调用其成员函数startWithTarget(CCNode pTarget)来绑定该动作的履行节点,和初始化动作类的成员变量。
这些工作都完成后,每一帧刷新屏幕时,体系就会在CCActionManager中遍历动作表中的每一个动作,并调用动作的step(float)办法。而step办法首要负责策画m_elapsed的值,并调用(float)办法。
void CCActionInterval::step(float dt)
{
if (m_bFirstTick)
{
m_bFirstTick = false;
m_elapsed = 0;
}
else
{
m_elapsed += dt;
}
this->(MAX (0, // needed for rewind. elapsed could be negative
MIN(1, m_elapsed / MAX(m_fDuration, FLT_EPSILON) // division by 0
)
)
);
}
传入办法的float型参数默示逝去的时候与动作完成须要的时候的比值,介于0-1之间,即动作完成的百分比。然后在办法中,经由过程完成比例对节点的属性进行操纵来达到动作的结果。
例如:对MoveBy调用时,经由过程传入的比例调用setPosition直接批改节点的属性。
最后在每一帧停止后,CCActionManager的会搜检动作队列中每个动作的isDone函数是否返回true,若是返回true,则动作停止,将其从队列中删除。
——————————————————————————————————————————————————————————————————————————
从上方知道:动作都是由CCActionManager来经管。那我们再来看看CCActionManager的工作道理。
在CCDirector初始化时,履行了如下代码:
// scheduler
m_pScheduler = new CCScheduler();
// action manager
m_pActionManager = new CCActionManager();
m_pScheduler->scheduleUpdateForTarget(m_pActionManager, krioritySystem, false);
可见动作经管类在创建时就注册了Update按时器,那么CCScheduler在游戏的每一帧mainLoop更新中都邑触发CCActionManager注册的(float )办法。调剂器道理请参照此链接:http://www.cnblogs.com/songcf/p/3162414.html
// main loop
void CCActionManager::(float dt)
{
//列举措作表中的每一个节点
for (tHashElement elt = m_pTargets; elt != NULL; )
{
m_pCurrentTarget = elt;
m_bCurrentTargetSalvaged = false;
if (! m_pCurrentTarget->paused)
{
//列举节点的每一个动作 actions数组可能会在轮回中被批改
for (m_pCurrentTarget->actionIndex = 0; m_pCurrentTarget->actionIndex < m_pCurrentTarget->actions->num;
m_pCurrentTarget->actionIndex++)
{
m_pCurrentTarget->currentAction = (CCAction)m_pCurrentTarget->actions->arr[m_pCurrentTarget->actionIndex];
if (m_pCurrentTarget->currentAction == NULL)
{
continue;
}
m_pCurrentTarget->currentActionSalvaged = false;
m_pCurrentTarget->currentAction->step(dt);
if (m_pCurrentTarget->currentActionSalvaged)
{
// The currentAction told the node to remove it. To prevent the action
// accidentally deallocating itself before finishing its step, we retained
// it. Now that step is done, its safe to release it.
m_pCurrentTarget->currentAction->release();
} else
if (m_pCurrentTarget->currentAction->isDone())
{
m_pCurrentTarget->currentAction->stop();
CCAction pAction = m_pCurrentTarget->currentAction;
// Make currentAction nil to prevent removeAction salvaging it.
m_pCurrentTarget->currentAction = NULL;
removeAction(pAction);
}
m_pCurrentTarget->currentAction = NULL;
}
}
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
elt = (tHashElement)(elt->hh.next);
// only currentTarget if no actions were scheduled during the cycle (issue #481)
if (m_bCurrentTargetSalvaged && m_pCurrentTarget->actions->num == 0)
{
HashElement(m_pCurrentTarget);
}
}
// issue #635
m_pCurrentTarget = NULL;
}
真正的心灵世界会告诉你根本看不见的东西,这东西需要你付出思想和灵魂的劳动去获取,然后它会照亮你的生命,永远照亮你的生命。——王安忆《小说家的十三堂课》