mirror of
https://github.com/photonstorm/phaser
synced 2025-02-17 06:28:30 +00:00
Large refactor after some performance profiling. Works a lot better as a single array. No deep iteration any more, and cleaner data structure.
This commit is contained in:
parent
b05e47c477
commit
568eb5e4b3
9 changed files with 161 additions and 77 deletions
|
@ -1,4 +1,4 @@
|
|||
var CHECKSUM = {
|
||||
build: '8ccbee50-4017-11e7-a8e1-659b1139a509'
|
||||
build: '68461dd0-4026-11e7-bdc5-9f162ef42266'
|
||||
};
|
||||
module.exports = CHECKSUM;
|
|
@ -12,7 +12,6 @@ module.exports = [
|
|||
'props',
|
||||
'repeat',
|
||||
'repeatDelay',
|
||||
'stagger',
|
||||
'startAt',
|
||||
'startDelay',
|
||||
'targets',
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
var TWEEN_CONST = require('./const');
|
||||
|
||||
var Tween = function (manager, targets, tweenData)
|
||||
var Tween = function (manager, data)
|
||||
{
|
||||
this.manager = manager;
|
||||
|
||||
// Array of targets being tweened (TweenTarget objects)
|
||||
this.targets = targets;
|
||||
|
||||
// targets array doesn't change, so we can cache the length
|
||||
this.totalTargets = targets.length;
|
||||
|
||||
// An array of TweenData objects, each containing a unique property being tweened.
|
||||
this.data = tweenData;
|
||||
// An array of TweenData objects, each containing a unique property and target being tweened.
|
||||
this.data = data;
|
||||
|
||||
// data array doesn't change, so we can cache the length
|
||||
this.totalData = tweenData.length;
|
||||
this.totalData = data.length;
|
||||
|
||||
// Cached target total (not necessarily the same as the data total)
|
||||
this.totalTargets = 0;
|
||||
|
||||
// If true then duration, delay, etc values are all frame totals
|
||||
this.useFrames = false;
|
||||
|
@ -31,7 +28,7 @@ var Tween = function (manager, targets, tweenData)
|
|||
// Time in ms/frames before the tween loops again if loop is true
|
||||
this.loopDelay = 0;
|
||||
|
||||
// Time in ms/frames before the 'onComplete' event fires.
|
||||
// Time in ms/frames before the 'onComplete' event fires. This never fires if loop = true (as it never completes)
|
||||
this.completeDelay = 0;
|
||||
|
||||
// Countdown timer (used by startDelay, loopDelay and completeDelay)
|
||||
|
@ -45,6 +42,7 @@ var Tween = function (manager, targets, tweenData)
|
|||
onStart: { callback: null, scope: null, params: null },
|
||||
onUpdate: { callback: null, scope: null, params: null },
|
||||
onRepeat: { callback: null, scope: null, params: null },
|
||||
onLoop: { callback: null, scope: null, params: null },
|
||||
onComplete: { callback: null, scope: null, params: null }
|
||||
};
|
||||
|
||||
|
|
|
@ -4,9 +4,8 @@ var Tween = require('./Tween');
|
|||
var RESERVED = require('./ReservedProps');
|
||||
var GetEaseFunction = require('./GetEaseFunction');
|
||||
var TweenData = require('./TweenData');
|
||||
var TweenTarget = require('./TweenTarget');
|
||||
|
||||
var GetTargets = function (config, props)
|
||||
var GetTargets = function (config)
|
||||
{
|
||||
var targets = GetValue(config, 'targets', null);
|
||||
|
||||
|
@ -20,21 +19,7 @@ var GetTargets = function (config, props)
|
|||
targets = [ targets ];
|
||||
}
|
||||
|
||||
var out = [];
|
||||
|
||||
for (var i = 0; i < targets.length; i++)
|
||||
{
|
||||
var keyData = {};
|
||||
|
||||
for (var p = 0; p < props.length; p++)
|
||||
{
|
||||
keyData[props[p].key] = { start: 0, current: 0, end: 0, startCache: null, endCache: null };
|
||||
}
|
||||
|
||||
out.push(TweenTarget(targets[i], keyData));
|
||||
}
|
||||
|
||||
return out;
|
||||
return targets;
|
||||
};
|
||||
|
||||
var GetProps = function (config)
|
||||
|
@ -133,13 +118,14 @@ var GetValueOp = function (key, value)
|
|||
}
|
||||
else if (t === 'function')
|
||||
{
|
||||
// Technically this could return a number, string or object
|
||||
// props: {
|
||||
// x: function () { return Math.random() * 10 },
|
||||
// y: someOtherCallback
|
||||
// x: function (startValue, target, index, totalTargets) { return startValue + (index * 50); },
|
||||
// }
|
||||
|
||||
valueCallback = GetValueOp(key, value.call());
|
||||
valueCallback = function (startValue, target, index, total)
|
||||
{
|
||||
return value(startValue, target, index, total);
|
||||
};
|
||||
}
|
||||
else if (value.hasOwnProperty('value'))
|
||||
{
|
||||
|
@ -155,20 +141,75 @@ var GetValueOp = function (key, value)
|
|||
return valueCallback;
|
||||
};
|
||||
|
||||
var GetBoolean = function (source, key, defaultValue)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
else if (source.hasOwnProperty(key))
|
||||
{
|
||||
return source[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
var GetNewValue = function (source, key, defaultValue)
|
||||
{
|
||||
var valueCallback;
|
||||
|
||||
if (source.hasOwnProperty(key))
|
||||
{
|
||||
var t = typeof(source[key]);
|
||||
|
||||
if (t === 'function')
|
||||
{
|
||||
valueCallback = function (index, totalTargets, target)
|
||||
{
|
||||
return source[key](index, totalTargets, target);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
valueCallback = function ()
|
||||
{
|
||||
return source[key];
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (typeof defaultValue === 'function')
|
||||
{
|
||||
valueCallback = defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueCallback = function ()
|
||||
{
|
||||
return defaultValue;
|
||||
};
|
||||
}
|
||||
|
||||
return valueCallback;
|
||||
};
|
||||
|
||||
var TweenBuilder = function (manager, config)
|
||||
{
|
||||
// Create arrays of the Targets and the Properties
|
||||
var targets = GetTargets(config);
|
||||
var props = GetProps(config);
|
||||
|
||||
// Default Tween values
|
||||
var ease = GetEaseFunction(GetValue(config, 'ease', 'Power0'));
|
||||
var duration = GetAdvancedValue(config, 'duration', 1000);
|
||||
var yoyo = GetValue(config, 'yoyo', false);
|
||||
var yoyoDelay = GetAdvancedValue(config, 'yoyoDelay', 0);
|
||||
var repeat = GetAdvancedValue(config, 'repeat', 0);
|
||||
var repeatDelay = GetAdvancedValue(config, 'repeatDelay', 0);
|
||||
var delay = GetAdvancedValue(config, 'delay', 0);
|
||||
var startAt = GetAdvancedValue(config, 'startAt', null);
|
||||
var duration = GetNewValue(config, 'duration', 1000);
|
||||
var yoyo = GetBoolean(config, 'yoyo', false);
|
||||
var yoyoDelay = GetNewValue(config, 'yoyoDelay', 0);
|
||||
var repeat = GetNewValue(config, 'repeat', 0);
|
||||
var repeatDelay = GetNewValue(config, 'repeatDelay', 0);
|
||||
var delay = GetNewValue(config, 'delay', 0);
|
||||
var startAt = GetNewValue(config, 'startAt', null);
|
||||
|
||||
var data = [];
|
||||
|
||||
|
@ -178,36 +219,38 @@ var TweenBuilder = function (manager, config)
|
|||
var key = props[p].key;
|
||||
var value = props[p].value;
|
||||
|
||||
var tweenData = TweenData(
|
||||
key,
|
||||
GetValueOp(key, value),
|
||||
GetEaseFunction(GetValue(value, 'ease', ease)),
|
||||
GetAdvancedValue(value, 'delay', delay),
|
||||
GetAdvancedValue(value, 'duration', duration),
|
||||
GetValue(value, 'yoyo', yoyo),
|
||||
GetAdvancedValue(value, 'yoyoDelay', yoyoDelay),
|
||||
GetAdvancedValue(value, 'repeat', repeat),
|
||||
GetAdvancedValue(value, 'repeatDelay', repeatDelay),
|
||||
GetAdvancedValue(value, 'startAt', startAt)
|
||||
);
|
||||
for (var t = 0; t < targets.length; t++)
|
||||
{
|
||||
// Swap for faster getters, if they want Advanced Value style things, they can do it via their own functions
|
||||
var tweenData = TweenData(
|
||||
targets[t],
|
||||
key,
|
||||
GetValueOp(key, value),
|
||||
GetEaseFunction(GetValue(value, 'ease', ease)),
|
||||
GetNewValue(value, 'delay', delay),
|
||||
GetNewValue(value, 'duration', duration),
|
||||
GetBoolean(value, 'yoyo', yoyo),
|
||||
GetNewValue(value, 'yoyoDelay', yoyoDelay),
|
||||
GetNewValue(value, 'repeat', repeat),
|
||||
GetNewValue(value, 'repeatDelay', repeatDelay),
|
||||
GetNewValue(value, 'startAt', startAt)
|
||||
);
|
||||
|
||||
// TODO: Calculate total duration
|
||||
// TODO: Calculate total duration
|
||||
|
||||
data.push(tweenData);
|
||||
data.push(tweenData);
|
||||
}
|
||||
}
|
||||
|
||||
var targets = GetTargets(config, props);
|
||||
var tween = new Tween(manager, data);
|
||||
|
||||
var tween = new Tween(manager, targets, data);
|
||||
|
||||
var stagger = GetAdvancedValue(config, 'stagger', 0);
|
||||
|
||||
tween.useFrames = GetValue(config, 'useFrames', false);
|
||||
tween.loop = GetValue(config, 'loop', false);
|
||||
tween.totalTargets = targets.length;
|
||||
tween.useFrames = GetBoolean(config, 'useFrames', false);
|
||||
tween.loop = GetBoolean(config, 'loop', false);
|
||||
tween.loopDelay = GetAdvancedValue(config, 'loopDelay', 0);
|
||||
tween.completeDelay = GetAdvancedValue(config, 'completeDelay', 0);
|
||||
tween.startDelay = GetAdvancedValue(config, 'startDelay', 0) + (stagger * targets.length);
|
||||
tween.paused = GetValue(config, 'paused', false);
|
||||
tween.startDelay = GetAdvancedValue(config, 'startDelay', 0);
|
||||
tween.paused = GetBoolean(config, 'paused', false);
|
||||
|
||||
return tween;
|
||||
};
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
var TweenData = function (key, value, ease, delay, duration, yoyo, yoyoDelay, repeat, repeatDelay, startAt)
|
||||
var TweenData = function (target, key, value, ease, delay, duration, yoyo, yoyoDelay, repeat, repeatDelay, startAt)
|
||||
{
|
||||
return {
|
||||
|
||||
// The target to tween
|
||||
target: target,
|
||||
|
||||
// The property of the target to tween
|
||||
key: key,
|
||||
|
||||
|
@ -12,25 +15,25 @@ var TweenData = function (key, value, ease, delay, duration, yoyo, yoyoDelay, re
|
|||
ease: ease,
|
||||
|
||||
// Duration of the tween in ms/frames, excludes time for yoyo or repeats.
|
||||
duration: duration,
|
||||
duration: 0,
|
||||
|
||||
// The total calculated duration of this TweenData (based on duration, repeat, delay and yoyo)
|
||||
totalDuration: 0,
|
||||
|
||||
// Time in ms/frames before tween will start.
|
||||
delay: delay,
|
||||
delay: 0,
|
||||
|
||||
// Cause the tween to return back to its start value after yoyoDelay has expired.
|
||||
yoyo: yoyo,
|
||||
|
||||
// Time in ms/frames the tween will pause before running the yoyo (only applied if yoyo is true)
|
||||
yoyoDelay: yoyoDelay,
|
||||
yoyoDelay: 0,
|
||||
|
||||
// Number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice.
|
||||
repeat: repeat,
|
||||
repeat: 0,
|
||||
|
||||
// Time in ms/frames before the repeat will start.
|
||||
repeatDelay: repeatDelay,
|
||||
repeatDelay: 0,
|
||||
|
||||
// Changes the property to be this value before starting the tween.
|
||||
startAt: startAt,
|
||||
|
@ -44,6 +47,21 @@ var TweenData = function (key, value, ease, delay, duration, yoyo, yoyoDelay, re
|
|||
// How many repeats are left to run?
|
||||
repeatCounter: 0,
|
||||
|
||||
// Value Data:
|
||||
|
||||
start: 0,
|
||||
current: 0,
|
||||
end: 0,
|
||||
|
||||
// LoadValue generation functions
|
||||
gen: {
|
||||
delay: delay,
|
||||
duration: duration,
|
||||
yoyoDelay: yoyoDelay,
|
||||
repeat: repeat,
|
||||
repeatDelay: repeatDelay
|
||||
},
|
||||
|
||||
// TWEEN_CONST.CREATED
|
||||
state: 0
|
||||
};
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
var TweenTarget = function (target, keys)
|
||||
{
|
||||
// keys: {
|
||||
// x: { start: 0, current: 0, end: 0, startCache: null, endCache: null },
|
||||
// y: { start: 0, current: 0, end: 0, startCache: null, endCache: null }
|
||||
// }
|
||||
|
||||
return {
|
||||
|
||||
ref: target,
|
||||
|
|
|
@ -2,9 +2,20 @@ var TWEEN_CONST = require('../const');
|
|||
|
||||
var ResetTweenData = function ()
|
||||
{
|
||||
for (var key in this.data)
|
||||
var data = this.data;
|
||||
var totalTargets = this.totalTargets;
|
||||
|
||||
for (var i = 0; i < this.totalData; i++)
|
||||
{
|
||||
var tweenData = this.data[key];
|
||||
var tweenData = data[i];
|
||||
var target = tweenData.target;
|
||||
var gen = tweenData.gen;
|
||||
|
||||
tweenData.delay = gen.delay(i, totalTargets, target);
|
||||
tweenData.duration = gen.duration(i, totalTargets, target);
|
||||
tweenData.yoyoDelay = gen.yoyoDelay(i, totalTargets, target);
|
||||
tweenData.repeat = gen.repeat(i, totalTargets, target);
|
||||
tweenData.repeatDelay = gen.repeatDelay(i, totalTargets, target);
|
||||
|
||||
tweenData.progress = 0;
|
||||
tweenData.elapsed = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var SetEventCallback = function (type, callback, params, scope)
|
||||
{
|
||||
var types = [ 'onStart', 'onUpdate', 'onRepeat', 'onComplete' ];
|
||||
var types = [ 'onStart', 'onUpdate', 'onRepeat', 'onLoop', 'onComplete' ];
|
||||
|
||||
if (types.indexOf(type) !== -1)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,9 @@ var SetStateFromEnd = function (tween, tweenData)
|
|||
{
|
||||
tweenData.elapsed = tweenData.repeatDelay;
|
||||
|
||||
tween.resetTargetsValue(tweenData);
|
||||
tweenData.current = tweenData.start;
|
||||
|
||||
tweenData.target[tweenData.key] = tweenData.current;
|
||||
|
||||
return TWEEN_CONST.REPEAT_DELAY;
|
||||
}
|
||||
|
@ -62,7 +64,9 @@ var SetStateFromStart = function (tween, tweenData)
|
|||
{
|
||||
tweenData.elapsed = tweenData.repeatDelay;
|
||||
|
||||
tween.resetTargetsValue(tweenData);
|
||||
tweenData.current = tweenData.start;
|
||||
|
||||
tweenData.target[tweenData.key] = tweenData.current;
|
||||
|
||||
return TWEEN_CONST.REPEAT_DELAY;
|
||||
}
|
||||
|
@ -106,7 +110,9 @@ var UpdateTweenData = function (tween, tweenData, delta)
|
|||
v = tweenData.ease(1 - progress);
|
||||
}
|
||||
|
||||
tween.calcTargetsValue(tweenData, v);
|
||||
tweenData.current = tweenData.start + ((tweenData.end - tweenData.start) * v);
|
||||
|
||||
tweenData.target[tweenData.key] = tweenData.current;
|
||||
|
||||
tweenData.elapsed = elapsed;
|
||||
tweenData.progress = progress;
|
||||
|
@ -164,7 +170,11 @@ var UpdateTweenData = function (tween, tweenData, delta)
|
|||
|
||||
case TWEEN_CONST.PENDING_RENDER:
|
||||
|
||||
tween.loadValues(tweenData);
|
||||
tweenData.start = tweenData.target[tweenData.key];
|
||||
tweenData.current = tweenData.start;
|
||||
tweenData.end = tweenData.value(tweenData.start);
|
||||
|
||||
tweenData.target[tweenData.key] = tweenData.current;
|
||||
|
||||
tweenData.state = TWEEN_CONST.PLAYING_FORWARD;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue