欢迎关注公众号:“Cocos Creator 源码讲解”,一起学习。
/**
* @module cc
*/
/*
* Runs actions sequentially, one after another.
* @class Sequence
* @extends ActionInterval
* @param {Array|FiniteTimeAction} tempArray
* @example
* // create sequence with actions
* var seq = new cc.Sequence(act1, act2);
*
* // create sequence with array
* var seq = new cc.Sequence(actArray);
*/
/* 按顺序、一个接一个地运行操作。 */
cc.Sequence = cc.Class({
name: 'cc.Sequence',
extends: cc.ActionInterval,
/* 构造函数 */
ctor: function (tempArray) {
/* 存储action到数组 */
this._actions = [];
this._split = null;
this._last = 0;
this._reversed = false;
/* sequance 的参数,必须有length属性,array类型的话直接用这个参数,假如不是,直接用arguments */
var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
if (paramArray.length === 1) {
/* Failed to construct, Sequence construction needs two or more actions. */
cc.errorID(1019);
return;
}
/* 参数array长度-1,最后一个位置的下标 */
var last = paramArray.length - 1;
if ((last >= 0) && (paramArray[last] == null))
/* parameters should not be ending with null in Javascript 最后一个参数不能为空 */
cc.logID(1015);
if (last >= 0) {
/* 获取第一个action,定义为pre;声明一个action1 变量 */
var prev = paramArray[0], action1;
for (var i = 1; i < last; i++) {
if (paramArray[i]) {
action1 = prev;
/*_actionOneTwo返回一个新sequence, */
prev = cc.Sequence._actionOneTwo(action1, paramArray[i]);
}
}
/* 初始化最后一个和倒数第二个 action */
this.initWithTwoActions(prev, paramArray[last]);
}
},
/*
* Initializes the action <br/>
* @param {FiniteTimeAction} actionOne
* @param {FiniteTimeAction} actionTwo
* @return {Boolean}
*/
/* 初始化的时候,有两个参数的情况 */
initWithTwoActions: function (actionOne, actionTwo) {
/* 两个action必须都不为空 */
if (!actionOne || !actionTwo) {
cc.errorID(1025);
return false;
}
/* 第一个action 和第二个action的运行时间 */
var durationOne = actionOne._duration, durationTwo = actionTwo._duration;
/* 假如存在循环次数,则分别获取总共需要消耗的时间 */
durationOne *= actionOne._repeatMethod ? actionOne._timesForRepeat : 1;
durationTwo *= actionTwo._repeatMethod ? actionTwo._timesForRepeat : 1;
/* 两个action的总时间 */
var d = durationOne + durationTwo;
/* 初始化父类参数,总共时间属性 */
this.initWithDuration(d);
/* 存储两个action */
this._actions[0] = actionOne;
this._actions[1] = actionTwo;
return true;
},
/* 复制一个队列 */
clone: function () {
var action = new cc.Sequence();
this._cloneDecoration(action);
action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone());
return action;
},
/* 执行startWithTarget */
startWithTarget: function (target) {
/* cc.Sequence[this] 调用 cc.ActionInterval的startWithTarget function ,参数为 target*/
cc.ActionInterval.prototype.startWithTarget.call(this, target);
/* 第一个action占用总时间的比例 */
this._split = this._actions[0]._duration / this._duration;
/* 这个action的单个占用比例,乘以次数,就是总共占用时间的比例 */
this._split *= this._actions[0]._repeatMethod ? this._actions[0]._timesForRepeat : 1;
this._last = -1;
},
/* 停止action队列 */
stop: function () {
// Issue #1305
/* 还没有播放完毕的时候 */
if (this._last !== -1)/* 获取当前正在播放的action进行stop */
this._actions[this._last].stop();
cc.Action.prototype.stop.call(this);
},
/* 每帧更新 */
update: function (dt) {
/*声明变量new_t, found */
var new_t, found = 0;
/* 获取分割时间, 声明变量locActions, locLast actionFound */
var locSplit = this._split, locActions = this._actions, locLast = this._last, actionFound;
dt = this._computeEaseTime(dt);
if (dt < locSplit) {
// action[0]
new_t = (locSplit !== 0) ? dt / locSplit : 1;
if (found === 0 && locLast === 1 && this._reversed) {
// Reverse mode ?
// XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode"
// since it will require a hack to know if an action is on reverse mode or not.
// "step" should be overriden, and the "reverseMode" value propagated to inner Sequences.
locActions[1].update(0);
locActions[1].stop();
}
} else {
// action[1]
found = 1;
new_t = (locSplit === 1) ? 1 : (dt - locSplit) / (1 - locSplit);
if (locLast === -1) {
// action[0] was skipped, execute it.//action[0] 被跳过,执行它。
locActions[0].startWithTarget(this.target);
locActions[0].update(1);
locActions[0].stop();
}
if (locLast === 0) {
// switching to action 1. stop action 0.// 切换到动作 1。停止动作 0。
locActions[0].update(1);
locActions[0].stop();
}
}
actionFound = locActions[found];
// Last action found and it is done.
/* // 找到最后一个操作并完成。 */
if (locLast === found && actionFound.isDone())
return;
// Last action not found// 未找到最后一个操作
if (locLast !== found)
actionFound.startWithTarget(this.target);
new_t = new_t * actionFound._timesForRepeat;
actionFound.update(new_t > 1 ? new_t % 1 : new_t);
this._last = found;
},
/* 翻转动作序列 */
reverse: function () {
var action = cc.Sequence._actionOneTwo(this._actions[1].reverse(), this._actions[0].reverse());
this._cloneDecoration(action);
this._reverseEaseList(action);
action._reversed = true;
return action;
}
});
/**
* !#en
* Helper constructor to create an array of sequenceable actions
* The created action will run actions sequentially, one after another.
* !#zh 顺序执行动作,创建的动作将按顺序依次运行。
* @method sequence
* @param {FiniteTimeAction|FiniteTimeAction[]} actionOrActionArray
* @param {FiniteTimeAction} ...tempArray
* @return {ActionInterval}
* @example
* // example
* // create sequence with actions
* var seq = cc.sequence(act1, act2);
*
* // create sequence with array
* var seq = cc.sequence(actArray);
*/
// todo: It should be use new
cc.sequence = function (/*Multiple Arguments*/tempArray) {
/*paramArray 假如是数组类型,直接适用,假如不是,用arguments属性, */
var paramArray = (tempArray instanceof Array) ? tempArray : arguments;
/* 长度为1的时候报错 */
if (paramArray.length === 1) {
cc.errorID(1019);
return null;
}
/* 最后一个index */
var last = paramArray.length - 1;
/* 大于一个参数,并且最后一个内容为空的话,报错 */
if ((last >= 0) && (paramArray[last] == null))
cc.logID(1015);
var result = null;
/* 大于一个参数,直接遍历 */
if (last >= 0) {
result = paramArray[0];
for (var i = 1; i <= last; i++) {
if (paramArray[i]) {
/* 遍历生成sequence */
result = cc.Sequence._actionOneTwo(result, paramArray[i]);
}
}
}
return result;
};
/* 初始化-两个action */
cc.Sequence._actionOneTwo = function (actionOne, actionTwo) {
var sequence = new cc.Sequence();
sequence.initWithTwoActions(actionOne, actionTwo);
return sequence;
};