当前位置: 首页>后端>正文

CocosCreator 源码.CCActionManager详解

require('../core/platform/CCClass');

var js = require('../core/platform/js');

/* 动作管理类 */

/*

* @class HashElement

* @constructor--构造函数

* @private--私有

*/

var HashElement = function () {

? ? this.actions = [];//存储具体的action

? ? this.target = null; //ccobject

? ? this.actionIndex = 0;

? ? this.currentAction = null; //CCAction

? ? this.paused = false;

? ? this.lock = false;

};

/**

* !#en

* cc.ActionManager is a class that can manage actions.<br/>

* Normally you won't need to use this class directly. 99% of the cases you will use the CCNode interface,

* which uses this class's singleton object.

* But there are some cases where you might need to use this class. <br/>

* Examples:<br/>

* - When you want to run an action where the target is different from a CCNode.<br/>

* - When you want to pause / resume the actions<br/>

* !#zh

* cc.ActionManager 是可以管理动作的单例类。<br/>

* 通常你并不需要直接使用这个类,99%的情况您将使用 CCNode 的接口。<br/>

* 但也有一些情况下,您可能需要使用这个类。 <br/>

* 例如:

*? - 当你想要运行一个动作,但目标不是 CCNode 类型时。 <br/>

*? - 当你想要暂停/恢复动作时。 <br/>

* @class ActionManager

* @example {@link cocos2d/core/CCActionManager/ActionManager.js}

*/

cc.ActionManager = function () {

? ? /* object 容器,存储了所有的动作node 的 uuid,*/

? ? /* 哈希map-object 存储node */

? ? this._hashTargets = js.createMap(true);

? ? /* 数组存储node */

? ? this._arrayTargets = [];

? ? /* 所有的存储的arr中的node,都在时时update,update时时运行的node,遍历的其中一个 */

? ? this._currentTarget = null;

? ? cc.director._scheduler && cc.director._scheduler.enableForTarget(this);

};

/* 设置cc.ActionManager的原型对象 */

cc.ActionManager.prototype = {

? ? constructor: cc.ActionManager,

? ? /* 元素池,数组类型 */

? ? _elementPool: [],

? ? /* 根据target查找element */

? ? _searchElementByTarget: function (arr, target) {

? ? ? ? for (var k = 0; k < arr.length; k++) {

? ? ? ? ? ? if (target === arr[k].target)

? ? ? ? ? ? ? ? return arr[k];

? ? ? ? }

? ? ? ? return null;

? ? },

? ? /* 获取一个element info,设置target,设置pause属性 */

? ? _getElement: function (target, paused) {

? ? ? ? var element = this._elementPool.pop();

? ? ? ? /* 当element不存在的时候,new一个 */

? ? ? ? if (!element) {

? ? ? ? ? ? element = new HashElement();

? ? ? ? }

? ? ? ? element.target = target;

? ? ? ? /* !!强制转换成布尔类型 */

? ? ? ? element.paused = !!paused;

? ? ? ? /* 返回element */

? ? ? ? return element;

? ? },

? ? /* 把element元素直接放到容器,重置element属性,回收 */

? ? _putElement: function (element) {

? ? ? ? /* node的actions数组的长度为0 */

? ? ? ? element.actions.length = 0;

? ? ? ? /*? */

? ? ? ? element.actionIndex = 0;

? ? ? ? /* 元素的当前action为空 */

? ? ? ? element.currentAction = null;

? ? ? ? /* 设置暂停属性为false */

? ? ? ? element.paused = false;

? ? ? ? /* 设置target为空 */

? ? ? ? element.target = null;

? ? ? ? /* 设置lock属性为false */

? ? ? ? element.lock = false;

? ? ? ? /* 回收info,放到pool池 */

? ? ? ? this._elementPool.push(element);

? ? },

? ? /**

? ? * !#en

? ? * Adds an action with a target.<br/>

? ? * If the target is already present, then the action will be added to the existing target.

? ? * If the target is not present, a new instance of this target will be created either paused or not, and the action will be added to the newly created target.

? ? * When the target is paused, the queued actions won't be 'ticked'.

? ? * !#zh

? ? * 增加一个动作,同时还需要提供动作的目标对象,目标对象是否暂停作为参数。<br/>

? ? * 如果目标已存在,动作将会被直接添加到现有的节点中。<br/>

? ? * 如果目标不存在,将为这一目标创建一个新的实例,并将动作添加进去。<br/>

? ? * 当目标状态的 paused 为 true,动作将不会被执行

? ? *

? ? * @method addAction

? ? * @param {Action} action

? ? * @param {Node} target

? ? * @param {Boolean} paused

? ? */

? ? addAction: function (action, target, paused) {

? ? ? ? if (!action || !target) {

? ? ? ? ? ? cc.errorID(1000);

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? //check if the action target already exists

? ? ? ? /* 检查操作目标是否已存在 */

? ? ? ? /* * !#zh 主要用于编辑器的 uuid,在编辑器下可用于持久化存储,在项目构建之后将变成自增的 id。

? ? ? ? */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? //if doesn't exists, create a hashelement and push in mpTargets

? ? ? ? /* 如果不存在,则创建一个 hashelement 并推入 mpTargets */

? ? ? ? if (!element) {

? ? ? ? ? ? element = this._getElement(target, paused);//获取一个element

? ? ? ? ? ? this._hashTargets[target._id] = element;//根据node uuid 存储info object存储

? ? ? ? ? ? this._arrayTargets.push(element);//array add info

? ? ? ? }

? ? ? ? else if (!element.actions) {//当element存在,并且element的actions-动作array为空

? ? ? ? ? ? element.actions = [];

? ? ? ? }

? ? ? ? element.actions.push(action);//info的action容器添加一个action

? ? ? ? action.startWithTarget(target);//action 设置target,

? ? },

? ? /**

? ? * !#en Removes all actions from all the targets.

? ? * !#zh 移除所有对象的所有动作。

? ? * @method removeAllActions

? ? */

? ? removeAllActions: function () {

? ? ? ? var locTargets = this._arrayTargets;

? ? ? ? /* 遍历数组-info */

? ? ? ? for (var i = 0; i < locTargets.length; i++) {

? ? ? ? ? ? var element = locTargets[i];

? ? ? ? ? ? if (element)

? ? ? ? ? ? ? ? this._putElement(element);//回收elementinfo

? ? ? ? }

? ? ? ? /* 清空数组 */

? ? ? ? this._arrayTargets.length = 0;

? ? ? ? //重新创建一个map 给hashTargets赋值

? ? ? ? this._hashTargets = js.createMap(true);

? ? },

? ? /**

? ? * !#en

? ? * Removes all actions from a certain target. <br/>

? ? * All the actions that belongs to the target will be removed.

? ? * !#zh

? ? * 移除指定对象上的所有动作。<br/>

? ? * 属于该目标的所有的动作将被删除。

? ? * @method removeAllActionsFromTarget

? ? * @param {Node} target

? ? * @param {Boolean} forceDelete

? ? */

? ? removeAllActionsFromTarget: function (target, forceDelete) {

? ? ? ? // explicit null handling

? ? ? ? if (target == null)

? ? ? ? ? ? return;

? ? ? ? /* 从map中找到对应的info */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? if (element) {

? ? ? ? ? ? /* 清空数组 */

? ? ? ? ? ? element.actions.length = 0;

? ? ? ? ? ? this._deleteHashElement(element);

? ? ? ? }

? ? },

? ? /**

? ? * !#en Removes an action given an action reference.

? ? * !#zh 移除指定的动作。

? ? * @method removeAction

? ? * @param {Action} action

? ? */

? ? removeAction: function (action) {

? ? ? ? // explicit null handling

? ? ? ? /* 空action处理 */

? ? ? ? if (!action) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? /* 获取原始目标节点。 */

? ? ? ? var target = action.getOriginalTarget();

? ? ? ? /* 从map中获取info--element */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? /* info不存在则return */

? ? ? ? if (!element) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? /* 遍历action数组 找到对应的action */

? ? ? ? for (var i = 0; i < element.actions.length; i++) {

? ? ? ? ? ? /* 找到对应的action */

? ? ? ? ? ? if (element.actions[i] === action) {

? ? ? ? ? ? ? ? /* 删除action */

? ? ? ? ? ? ? ? element.actions.splice(i, 1);

? ? ? ? ? ? ? ? // update actionIndex in case we are in tick. looping over the actions

? ? ? ? ? ? ? ? /* 如果我们处于勾选状态,请更新actionIndex。循环操作 */

? ? ? ? ? ? ? ? if (element.actionIndex >= i)

? ? ? ? ? ? ? ? ? ? element.actionIndex--;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? }

? ? },

? ? /* 根据action的tag,移除某个node的action */

? ? _removeActionByTag(tag, element, target) {

? ? ? ? /* 遍历某个具体info下的所有action */

? ? ? ? for (var i = 0, l = element.actions.length; i < l; ++i) {

? ? ? ? ? ? var action = element.actions[i];

? ? ? ? ? ? /* 某个action的tag和要找的tag一致 */

? ? ? ? ? ? if (action && action.getTag() === tag) {

? ? ? ? ? ? ? ? /* 如果target和action的target属性不一致,则跳过 */

? ? ? ? ? ? ? ? if (target && action.getOriginalTarget() !== target) {

? ? ? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? /* 从action数组中删除具体的action */

? ? ? ? ? ? ? ? this._removeActionAtIndex(i, element);

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? }

? ? },

? ? /**

? ? * !#en Removes an action given its tag and the target.

? ? * !#zh 删除指定对象下特定标签的一个动作,将删除首个匹配到的动作。

? ? * @method removeActionByTag

? ? * @param {Number} tag

? ? * @param {Node} [target]

? ? */

? ? removeActionByTag: function (tag, target) {

? ? ? ? /* tag不合法 */

? ? ? ? if (tag === cc.Action.TAG_INVALID)

? ? ? ? ? ? cc.logID(1002);

? ? ? ? /* 哈希map容器 */

? ? ? ? let hashTargets = this._hashTargets;

? ? ? ? if (target) {

? ? ? ? ? ? var element = hashTargets[target._id];

? ? ? ? ? ? /* info找到 */

? ? ? ? ? ? if (element) {

? ? ? ? ? ? ? ? this._removeActionByTag(tag, element, target);

? ? ? ? ? ? }

? ? ? ? }/* 假如target参数为空,则遍历所有匹配key 根据找到的info进行传参删除 */

? ? ? ? else {

? ? ? ? ? ? for (let name in hashTargets) {

? ? ? ? ? ? ? ? let element = hashTargets[name];

? ? ? ? ? ? ? ? this._removeActionByTag(tag, element);

? ? ? ? ? ? }

? ? ? ? }

? ? },

? ? /**

? ? * !#en Gets an action given its tag an a target.

? ? * !#zh 通过目标对象和标签获取一个动作。

? ? * @method getActionByTag

? ? * @param {Number} tag

? ? * @param {Node} target

? ? * @return {Action|Null}? return the Action with the given tag on success

? ? */

? ? getActionByTag: function (tag, target) {

? ? ? ? /* tag不合法报错 */

? ? ? ? if (tag === cc.Action.TAG_INVALID)

? ? ? ? ? ? cc.logID(1004);

? ? ? ? /* 根据targed的id获取到info */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? if (element) {

? ? ? ? ? ? /* info的actions数组不为空,进行遍历actions,进行tag比较 */

? ? ? ? ? ? if (element.actions != null) {

? ? ? ? ? ? ? ? for (var i = 0; i < element.actions.length; ++i) {

? ? ? ? ? ? ? ? ? ? var action = element.actions[i];

? ? ? ? ? ? ? ? ? ? if (action && action.getTag() === tag)

? ? ? ? ? ? ? ? ? ? ? ? return action;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? cc.logID(1005, tag);

? ? ? ? }

? ? ? ? return null;

? ? },

? ? /**

? ? * !#en

? ? * Returns the numbers of actions that are running in a certain target. <br/>

? ? * Composable actions are counted as 1 action. <br/>

? ? * Example: <br/>

? ? * - If you are running 1 Sequence of 7 actions, it will return 1. <br/>

? ? * - If you are running 7 Sequences of 2 actions, it will return 7.

? ? * !#zh

? ? * 返回指定对象下所有正在运行的动作数量。 <br/>

? ? * 组合动作被算作一个动作。<br/>

? ? * 例如:<br/>

? ? *? - 如果您正在运行 7 个动作组成的序列动作(Sequence),这个函数将返回 1。<br/>

? ? *? - 如果你正在运行 2 个序列动作(Sequence)和 5 个普通动作,这个函数将返回 7。<br/>

? ? *

? ? * @method getNumberOfRunningActionsInTarget

? ? * @param {Node} target

? ? * @return {Number}

? ? */

? ? /* 返回指定对象下所有正在运行的动作数量 */

? ? getNumberOfRunningActionsInTarget: function (target) {

? ? ? ? /* 找对应的info */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? /* 返回数组的长度 */

? ? ? ? if (element)

? ? ? ? ? ? return (element.actions) element.actions.length : 0;

? ? ? ? return 0;

? ? },

? ? /**

? ? * !#en Pauses the target: all running actions and newly added actions will be paused.

? ? * !#zh 暂停指定对象:所有正在运行的动作和新添加的动作都将会暂停。

? ? * @method pauseTarget

? ? * @param {Node} target

? ? */

? ? /* 暂停某个对象的所有action */

? ? pauseTarget: function (target) {

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? if (element)

? ? ? ? ? ? element.paused = true;

? ? },

? ? /**

? ? * !#en Resumes the target. All queued actions will be resumed.

? ? * !#zh 让指定目标恢复运行。在执行序列中所有被暂停的动作将重新恢复运行。

? ? * @method resumeTarget

? ? * @param {Node} target

? ? */

? ? /* 回复action的运行 */

? ? resumeTarget: function (target) {

? ? ? ? /* 根据对象id获取info */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? if (element)

? ? ? ? ? ? element.paused = false;

? ? },

? ? /**

? ? * !#en Pauses all running actions, returning a list of targets whose actions were paused.

? ? * !#zh 暂停所有正在运行的动作,返回一个包含了那些动作被暂停了的目标对象的列表。

? ? * @method pauseAllRunningActions

? ? * @return {Array}? a list of targets whose actions were paused.

? ? */

? ? /* 暂停所有正在运行的动作,返回一个包含了那些动作被暂停了的目标对象的列表。 */

? ? pauseAllRunningActions: function () {

? ? ? ? var idsWithActions = [];

? ? ? ? /* 存储info的数组 */

? ? ? ? var locTargets = this._arrayTargets;

? ? ? ? /* 遍历容器 */

? ? ? ? for (var i = 0; i < locTargets.length; i++) {

? ? ? ? ? ? var element = locTargets[i];

? ? ? ? ? ? /* info没pause的,设置为pause为true */

? ? ? ? ? ? if (element && !element.paused) {

? ? ? ? ? ? ? ? element.paused = true;

? ? ? ? ? ? ? ? /* 把对应都放到数组 */

? ? ? ? ? ? ? ? idsWithActions.push(element.target);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? /* 返回数组 */

? ? ? ? return idsWithActions;

? ? },

? ? /**

? ? * !#en Resume a set of targets (convenience function to reverse a pauseAllRunningActions or pauseTargets call).

? ? * !#zh 让一组指定对象恢复运行(用来逆转 pauseAllRunningActions 效果的便捷函数)。

? ? * @method resumeTargets

? ? * @param {Array} targetsToResume

? ? */

? ? resumeTargets: function (targetsToResume) {

? ? ? ? /* 参数必须是数组,不为空 */

? ? ? ? if (!targetsToResume)

? ? ? ? ? ? return;

? ? ? ? /* 遍历数组,获取所有具体对象 */

? ? ? ? for (var i = 0; i < targetsToResume.length; i++) {

? ? ? ? ? ? if (targetsToResume[i])

? ? ? ? ? ? ? ? this.resumeTarget(targetsToResume[i]);

? ? ? ? }

? ? },

? ? /**

? ? * !#en Pause a set of targets.

? ? * !#zh 暂停一组指定对象。

? ? * @method pauseTargets

? ? * @param {Array} targetsToPause

? ? */

? ? pauseTargets: function (targetsToPause) {

? ? ? ? if (!targetsToPause)

? ? ? ? ? ? return;

? ? ? ? /* 遍历存储对象的数组 */

? ? ? ? for (var i = 0; i < targetsToPause.length; i++) {

? ? ? ? ? ? if (targetsToPause[i])

? ? ? ? ? ? ? ? this.pauseTarget(targetsToPause[i]);

? ? ? ? }

? ? },

? ? /**

? ? * !#en

? ? * purges the shared action manager. It releases the retained instance. <br/>

? ? * because it uses this, so it can not be static.

? ? * !#zh

? ? * 清除共用的动作管理器。它释放了持有的实例。 <br/>

? ? * 因为它使用 this,因此它不能是静态的。

? ? * @method purgeSharedManager

? ? */

? ? purgeSharedManager: function () {

? ? ? ? /* 取消指定对象的 update 定时器。 */

? ? ? ? cc.director.getScheduler().unscheduleUpdate(this);

? ? },

? ? //protected

? ? /* 删除固定数组下标的info */

? ? _removeActionAtIndex: function (index, element) {

? ? ? ? /* 获取固定的action */

? ? ? ? var action = element.actions[index];

? ? ? ? /* 删除某个index的属性 */

? ? ? ? element.actions.splice(index, 1);

? ? ? ? // update actionIndex in case we are in tick. looping over the actions

? ? ? ? /* 如果我们处于勾选状态,请更新actionIndex。循环操作 */

? ? ? ? if (element.actionIndex >= index)

? ? ? ? ? ? element.actionIndex--;

? ? ? ? ? ? /* 当action数组为空的时候,删除这个info */

? ? ? ? if (element.actions.length === 0) {

? ? ? ? ? ? this._deleteHashElement(element);

? ? ? ? }

? ? },

? ? /* 删除map内存储的这个info */

? ? _deleteHashElement: function (element) {

? ? ? ? var ret = false;

? ? ? ? if (element && !element.lock) {

? ? ? ? ? ? if (this._hashTargets[element.target._id]) {

? ? ? ? ? ? ? ? /* 从object 删除info */

? ? ? ? ? ? ? ? delete this._hashTargets[element.target._id];

? ? ? ? ? ? ? ? var targets = this._arrayTargets;

? ? ? ? ? ? ? ? /* 遍历数组 */

? ? ? ? ? ? ? ? for (var i = 0, l = targets.length; i < l; i++) {

? ? ? ? ? ? ? ? ? ? if (targets[i] === element) {

? ? ? ? ? ? ? ? ? ? ? ? targets.splice(i, 1);//删除这个元素,从数组中

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? /* 回收info */

? ? ? ? ? ? ? ? this._putElement(element);

? ? ? ? ? ? ? ? ret = true;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return ret;

? ? },

? ? /**

? ? * !#en The ActionManager update。

? ? * !#zh ActionManager 主循环。

? ? * @method update

? ? * @param {Number} dt delta time in seconds

? ? */

? ? update: function (dt) {

? ? ? ? /* 声明locCurrTarget 临时变量存储的是info? locTargets是数组this._arrayTargets的重新赋值 */

? ? ? ? var locTargets = this._arrayTargets, locCurrTarget;

? ? ? ? for (var elt = 0; elt < locTargets.length; elt++) {

? ? ? ? ? ? this._currentTarget = locTargets[elt];

? ? ? ? ? ? /* 设置当前target info */

? ? ? ? ? ? locCurrTarget = this._currentTarget;

? ? ? ? ? ? /* action没有被暂停,并且存在actions */

? ? ? ? ? ? if (!locCurrTarget.paused && locCurrTarget.actions) {

? ? ? ? ? ? ? ? locCurrTarget.lock = true;

? ? ? ? ? ? ? ? // The 'actions' CCMutableArray may change while inside this loop.

? ? ? ? ? ? ? ? /* 在此循环内,“动作”CCMutableArray 可能会发生变化。 */

? ? ? ? ? ? ? ? for (locCurrTarget.actionIndex = 0; locCurrTarget.actionIndex < locCurrTarget.actions.length; locCurrTarget.actionIndex++) {

? ? ? ? ? ? ? ? ? ? locCurrTarget.currentAction = locCurrTarget.actions[locCurrTarget.actionIndex];

? ? ? ? ? ? ? ? ? ? if (!locCurrTarget.currentAction)

? ? ? ? ? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? ? ? ? ? //use for speed

? ? ? ? ? ? ? ? ? ? locCurrTarget.currentAction.step(dt * (locCurrTarget.currentAction._speedMethod locCurrTarget.currentAction._speed : 1));

? ? ? ? ? ? ? ? ? ? if (locCurrTarget.currentAction && locCurrTarget.currentAction.isDone()) {

? ? ? ? ? ? ? ? ? ? ? ? locCurrTarget.currentAction.stop();

? ? ? ? ? ? ? ? ? ? ? ? var action = locCurrTarget.currentAction;

? ? ? ? ? ? ? ? ? ? ? ? // Make currentAction nil to prevent removeAction from salvaging it.

? ? ? ? ? ? ? ? ? ? ? ? /* 将 currentAction 设置为 nil 以防止 removeAction 抢救它。 */

? ? ? ? ? ? ? ? ? ? ? ? locCurrTarget.currentAction = null;

? ? ? ? ? ? ? ? ? ? ? ? /* 移除指定动作 */

? ? ? ? ? ? ? ? ? ? ? ? this.removeAction(action);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? locCurrTarget.currentAction = null;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? locCurrTarget.lock = false;

? ? ? ? ? ? }

? ? ? ? ? ? // only delete currentTarget if no actions were scheduled during the cycle (issue #481)

? ? ? ? ? ? /* 仅当周期内未安排任何操作时才删除 currentTarget(问题 #481) */

? ? ? ? ? ? if (locCurrTarget.actions.length === 0) {//回收info

? ? ? ? ? ? ? ? this._deleteHashElement(locCurrTarget) && elt--;

? ? ? ? ? ? }

? ? ? ? }

? ? }

};

/* 测试环境,拓展属性isTargetPaused_TEST ,判断某个node的动画是否是paused */

if (CC_TEST) {

? ? cc.ActionManager.prototype.isTargetPaused_TEST = function (target) {

? ? ? ? /* 获取某个info */

? ? ? ? var element = this._hashTargets[target._id];

? ? ? ? return element.paused;

? ? };

}


https://www.xamrdz.com/backend/3xn1926043.html

相关文章: