ryanwilliams/cocos2d-javascript — Issue #23: array implementation of Sequence
Author: araker
Created: 2012-01-25 04:14:18+00:00
State: open

I never liked the nested implementation of CCSequence, so I've made a array version of it for cocos2d-iphone. The original code can be found here..

http://www.cocos2d-iphone.org/forum/topic/27743

This is the javascript variant:

var Sequence = ActionInterval.extend(/** @lends cocos.actions.Sequence# */{
/**
* Array of actions to run
* @type cocos.nodes.Node[]
*/
actions: null,

split: 0,
currentAction: 0,

/**
* @class Runs a pair of actions sequentially, one after another
*
* @memberOf cocos.actions
* @constructs
* @extends cocos.actions.ActionInterval
*
* @opt {cocos.actions.FiniteTimeAction} one 1st action to run
* @opt {cocos.actions.FiniteTimeAction} two 2nd action to run
*/
init: function (opts) {

if (opts.actions.length == 0)
throw "Sequence arguments must be non-nil";

this.actions = opts.actions;
var d = 0;
for (var i=0; i= this.split)
{
//this one is finished
current.update(1);
current.stop();

this.currentAction+=1;

if (t != 1)
{
//explicitely test for t != 1 since split_ can have rounding errors
//going to new item, also check if no items have been skipped
while (t >= this.split)
{//true at least once

current=this.actions[this.currentAction];

if (current.get('target') != null) //actions like CCCallFunc are initialized with a target
current.startWithTarget(current.get('target'));
else
current.startWithTarget(this.target);

//elapsed will be > start time of new action, so the new delta is actually elapsed - start time of new action and not the current dt
correction = (t - split) * this.duration;

this.split += current.get('duration') / this.duration;

if (t >= this.split)
{//end time of action is smaller than t, action needs to be completed immediately

current.update(1);
current.stop();
this.currentAction_+=1;
}
}
}
}

if (t!=1)
{
//substract start time of current action from t, get corresponding duration (in sec), convert to relative time of current action
//use t * duration instead of elapsed, this way a sequence can be nested into other actions as well

if (correction > 0.0)
{
new_t = correction / current.duration();
}
else
{
var curDuration = current.get('duration');
new_t = ( (t * this.duration) - (this.split * this.duration - curDuration )) / curDuration;
current.update(new_t);
}
}
else
{//check if all actions have been completed

var nActions=this.actions.length -1;
for (; this.currentAction <= nActions; this.currentAction++)
{
current=this.actions[this.currentAction];

if (current.get('target') != null)
current.startWithTarget(current.get('target'));
else
current.startWithTarget(this.target);
current.update(1);
current.stop();
}
}
}
else
{
throw "Array Sequence out of bounds";
}
},

copy: function () {
// Constructor will copy actions
return Sequence.create({actions: this.get('actions')});
},

reverse: function() {
var tempArray = [];
var j = 0;
for (var i = this.actions.length; i >= 0; i--)
{
tempArray[j] = this.actions[i];
}
return Sequence.create({actions: tempArray});
}

});

The update method is longer than in the nested version, but it also corrects the delta and makes sure that the sequence can be nested into other actions (or in another sequence). I haven't tested out the javascript version much, but the objective-c code is well tested in my cocos game.

If I make any further changes to the source, i'll clone the repository and send you a pull request instead.