Tidied up the Animation folder.

Animation Manager now in its own folder, with all methods split out to their own files.
Animation Components moved to components folder.
AnimationFrame renamed to Frame and moved inside the frame folder, as it's frame specific.
This commit is contained in:
Richard Davey 2017-04-12 13:53:55 +01:00
parent da3496a71d
commit ee5e4f5195
38 changed files with 321 additions and 309 deletions

View file

@ -1,298 +0,0 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2016 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Animation = require('./frame/Animation');
var Map = require('../structs/Map');
var Pad = require('../utils/string/Pad');
var GetObjectValue = require('../utils/object/GetObjectValue');
/**
* Animations are managed by the global AnimationManager. This is a singleton class that is
* responsible for creating and delivering animations and their corresponding data to Game Objects.
*
* Sprites and other Game Objects get the data they need from the AnimationManager.
*
* Access it via `state.anims`.
*
* @class Phaser.AnimationManager
* @constructor
*/
var AnimationManager = function (game)
{
this.game = game;
this.textureManager = null;
this.globalTimeScale = 1;
this.anims = new Map();
};
AnimationManager.prototype.constructor = AnimationManager;
AnimationManager.prototype = {
boot: function (textureManager)
{
this.textureManager = textureManager;
},
// config format:
// {
// frames: [
// { key: textureKey, frame: textureFrame },
// { key: textureKey, frame: textureFrame, duration: float }
// { key: textureKey, frame: textureFrame, visible: boolean }
// { key: textureKey, frame: textureFrame, onUpdate: function }
// ]
// framerate: integer
// duration: float (seconds, optional, ignored if framerate is set)
// skipMissedFrames: boolean
// delay: integer
// repeat: integer (-1 = forever)
// repeatDelay: integer
// yoyo: boolean
// showOnStart: boolean
// hideOnComplete: boolean
// callbackScope: Object
// onStart: function
// onStartParams: array
// onRepeat: function
// onRepeatParams: array
// onUpdate: function
// onUpdateParams: array
// onComplete: function
// onCompleteParams: array
// transitions: [
// {
// key: string <- key of the animation to blend with,
// frames: [] <- play these frames before starting key
// }
// ]
// }
add: function (key, animation)
{
if (this.anims.has(key))
{
console.error('Animation with key', key, 'already exists');
return;
}
animation.key = key;
this.anims.set(key, animation);
return this;
},
create: function (key, config)
{
if (this.anims.has(key))
{
console.error('Animation with key', key, 'already exists');
return;
}
var anim = new Animation(this, key, config);
this.anims.set(key, anim);
return anim;
},
get: function (key)
{
return this.anims.get(key);
},
remove: function (key)
{
var anim = this.get(key);
if (anim)
{
this.anims.delete(key);
}
return anim;
},
// Load an Animation into a Game Objects Animation Component
load: function (child, key, startFrame)
{
var anim = this.get(key);
if (anim)
{
anim.load(child, startFrame);
}
return child;
},
play: function (key, child)
{
if (!Array.isArray(child))
{
child = [ child ];
}
var anim = this.get(key);
if (!anim)
{
return;
}
for (var i = 0; i < child.length; i++)
{
child[i].anims.play(key);
}
return this;
},
staggerPlay: function (key, child, stagger)
{
if (stagger === undefined) { stagger = 0; }
if (!Array.isArray(child))
{
child = [ child ];
}
var anim = this.get(key);
if (!anim)
{
return;
}
for (var i = 0; i < child.length; i++)
{
child[i].anims.delayedPlay(stagger * i, key);
}
return this;
},
generateFrameNumbers: function (key, config)
{
var startFrame = GetObjectValue(config, 'start', 0);
var endFrame = GetObjectValue(config, 'end', -1);
var firstFrame = GetObjectValue(config, 'first', false);
var out = GetObjectValue(config, 'framesArray', []);
var texture = this.textureManager.get(key);
if (!texture)
{
return out;
}
// No endFrame then see if we can get it
if (endFrame === -1)
{
endFrame = texture.frameTotal;
}
if (firstFrame && texture.has(firstFrame))
{
out.push({ key: key, frame: firstFrame });
}
for (var i = startFrame; i <= endFrame; i++)
{
if (texture.has(i))
{
out.push({ key: key, frame: i });
}
}
return out;
},
/**
* Really handy function for when you are creating arrays of animation data but it's using frame names and not numbers.
* For example imagine you've got 30 frames named: 'explosion_0001-large' to 'explosion_0030-large'
* You could use this function to generate those by doing: Phaser.Animation.generateFrameNames('explosion_', 1, 30, '-large', 4);
*
* @method Phaser.Animation.generateFrameNames
* @static
* @param {string} prefix - The start of the filename. If the filename was 'explosion_0001-large' the prefix would be 'explosion_'.
* @param {number} start - The number to start sequentially counting from. If your frames are named 'explosion_0001' to 'explosion_0034' the start is 1.
* @param {number} stop - The number to count to. If your frames are named 'explosion_0001' to 'explosion_0034' the stop value is 34.
* @param {string} [suffix=''] - The end of the filename. If the filename was 'explosion_0001-large' the prefix would be '-large'.
* @param {number} [zeroPad=0] - The number of zeros to pad the min and max values with. If your frames are named 'explosion_0001' to 'explosion_0034' then the zeroPad is 4.
* @return {string[]} An array of framenames.
*/
generateFrameNames: function (key, config)
{
var prefix = GetObjectValue(config, 'prefix', '');
var start = GetObjectValue(config, 'start', 0);
var end = GetObjectValue(config, 'end', 0);
var suffix = GetObjectValue(config, 'suffix', '');
var zeroPad = GetObjectValue(config, 'zeroPad', 0);
var out = GetObjectValue(config, 'framesArray', []);
var diff = (start < end) ? 1 : -1;
// Adjust because we use i !== end in the for loop
end += diff;
var texture = this.textureManager.get(key);
if (!texture)
{
return out;
}
for (var i = start; i !== end; i += diff)
{
var frame = prefix + Pad(i, zeroPad, '0', 1) + suffix;
if (texture.has(frame))
{
out.push({ key: key, frame: frame });
}
}
return out;
},
toJSON: function (key)
{
if (key !== undefined)
{
return this.anims.get(key).toJSON();
}
else
{
var output = {
anims: [],
globalTimeScale: this.globalTimeScale
};
this.anims.each(function (key, anim)
{
output.anims.push(anim.toJSON());
});
return output;
}
},
destroy: function ()
{
// TODO
}
};
module.exports = AnimationManager;

View file

@ -7,6 +7,9 @@ var Animation = function (manager, key, config)
this.key = key;
// A frame based animation (as opposed to a bone based animation)
this.type = 'frame';
// Extract all the frame data into the frames array
this.frames = GetFrames(manager.textureManager, GetObjectValue(config, 'frames', []));
@ -257,7 +260,7 @@ Animation.prototype = {
{
var output = {
key: this.key,
type: 'frame',
type: this.type,
frames: [],
framerate: this.frameRate,
duration: this.duration,

View file

@ -1,4 +1,4 @@
var AnimationFrame = function (textureKey, textureFrame, index, frame)
var Frame = function (textureKey, textureFrame, index, frame)
{
// The keys into the Texture Manager of the texture + frame this uses
this.textureKey = textureKey;
@ -33,9 +33,9 @@ var AnimationFrame = function (textureKey, textureFrame, index, frame)
this.visible = false;
};
AnimationFrame.prototype.constructor = AnimationFrame;
Frame.prototype.constructor = Frame;
AnimationFrame.prototype = {
Frame.prototype = {
toJSON: function ()
{
@ -55,4 +55,4 @@ AnimationFrame.prototype = {
};
module.exports = AnimationFrame;
module.exports = Frame;

View file

@ -1,4 +1,4 @@
var AnimationFrame = require('../AnimationFrame');
var Frame = require('./Frame');
var GetObjectValue = require('../../utils/object/GetObjectValue');
var GetFrames = function (textureManager, frames)
@ -33,7 +33,7 @@ var GetFrames = function (textureManager, frames)
var textureFrame = textureManager.getFrame(key, frame);
animationFrame = new AnimationFrame(key, frame, index, textureFrame);
animationFrame = new Frame(key, frame, index, textureFrame);
animationFrame.duration = GetObjectValue(item, 'duration', 0);
animationFrame.onUpdate = GetObjectValue(item, 'onUpdate', null);

View file

@ -1,4 +1,6 @@
// Phaser.Animation.Frame
// Phaser.Animation.Frame.Components
// Used by the GameObject Animation Component
module.exports = {

View file

@ -0,0 +1,32 @@
{
frames: [
{ key: textureKey, frame: textureFrame },
{ key: textureKey, frame: textureFrame, duration: float },
{ key: textureKey, frame: textureFrame, visible: boolean },
{ key: textureKey, frame: textureFrame, onUpdate: function }
],
framerate: integer,
duration: float (seconds, optional, ignored if framerate is set),
skipMissedFrames: boolean,
delay: integer,
repeat: integer (-1 = forever),
repeatDelay: integer,
yoyo: boolean,
showOnStart: boolean,
hideOnComplete: boolean,
callbackScope: Object,
onStart: function,
onStartParams: array,
onRepeat: function,
onRepeatParams: array,
onUpdate: function,
onUpdateParams: array,
onComplete: function,
onCompleteParams: array,
transitions: [
{
key: string <- key of the animation to blend with,
frames: [] <- play these frames before starting key
}
]
}

View file

@ -0,0 +1,16 @@
var AddAnimation = function (key, animation)
{
if (this.anims.has(key))
{
console.error('Animation with key', key, 'already exists');
return;
}
animation.key = key;
this.anims.set(key, animation);
return this;
};
module.exports = AddAnimation;

View file

@ -0,0 +1,57 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2016 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Map = require('../../structs/Map');
/**
* Animations are managed by the global AnimationManager. This is a singleton class that is
* responsible for creating and delivering animations and their corresponding data to Game Objects.
*
* Sprites and other Game Objects get the data they need from the AnimationManager.
*
* Access it via `state.anims`.
*
* @class Phaser.AnimationManager
* @constructor
*/
var AnimationManager = function (game)
{
this.game = game;
this.textureManager = null;
this.globalTimeScale = 1;
this.anims = new Map();
};
AnimationManager.prototype.constructor = AnimationManager;
AnimationManager.prototype = {
boot: function (textureManager)
{
this.textureManager = textureManager;
},
add: require('./AddAnimation'),
create: require('./CreateFrameAnimation'),
get: require('./GetAnimation'),
remove: require('./RemoveAnimation'),
load: require('./LoadAnimationToGameObject'),
play: require('./PlayAnimation'),
staggerPlay: require('./StaggerPlayAnimation'),
generateFrameNumbers: require('./GenerateFrameNumbers'),
generateFrameNames: require('./GenerateFrameNames'),
toJSON: require('./ToJSON'),
destroy: function ()
{
// TODO
}
};
module.exports = AnimationManager;

View file

@ -0,0 +1,18 @@
var Animation = require('../frame/Animation');
var CreateFrameAnimation = function (key, config)
{
if (this.anims.has(key))
{
console.error('Animation with key', key, 'already exists');
return;
}
var anim = new Animation(this, key, config);
this.anims.set(key, anim);
return anim;
};
module.exports = CreateFrameAnimation;

View file

@ -0,0 +1,38 @@
var GetObjectValue = require('../../utils/object/GetObjectValue');
var Pad = require('../../utils/string/Pad');
var GenerateFrameNames = function (key, config)
{
var prefix = GetObjectValue(config, 'prefix', '');
var start = GetObjectValue(config, 'start', 0);
var end = GetObjectValue(config, 'end', 0);
var suffix = GetObjectValue(config, 'suffix', '');
var zeroPad = GetObjectValue(config, 'zeroPad', 0);
var out = GetObjectValue(config, 'framesArray', []);
var diff = (start < end) ? 1 : -1;
// Adjust because we use i !== end in the for loop
end += diff;
var texture = this.textureManager.get(key);
if (!texture)
{
return out;
}
for (var i = start; i !== end; i += diff)
{
var frame = prefix + Pad(i, zeroPad, '0', 1) + suffix;
if (texture.has(frame))
{
out.push({ key: key, frame: frame });
}
}
return out;
};
module.exports = GenerateFrameNames;

View file

@ -0,0 +1,40 @@
var GetObjectValue = require('../../utils/object/GetObjectValue');
var GenerateFrameNumbers = function (key, config)
{
var startFrame = GetObjectValue(config, 'start', 0);
var endFrame = GetObjectValue(config, 'end', -1);
var firstFrame = GetObjectValue(config, 'first', false);
var out = GetObjectValue(config, 'framesArray', []);
var texture = this.textureManager.get(key);
if (!texture)
{
return out;
}
// No endFrame then see if we can get it
if (endFrame === -1)
{
endFrame = texture.frameTotal;
}
if (firstFrame && texture.has(firstFrame))
{
out.push({ key: key, frame: firstFrame });
}
for (var i = startFrame; i <= endFrame; i++)
{
if (texture.has(i))
{
out.push({ key: key, frame: i });
}
}
return out;
};
module.exports = GenerateFrameNumbers;

View file

@ -0,0 +1,6 @@
var GetAnimation = function (key)
{
return this.anims.get(key);
};
module.exports = GetAnimation;

View file

@ -0,0 +1,14 @@
// Load an Animation into a Game Objects Animation Component
var LoadAnimationToGameObject = function (child, key, startFrame)
{
var anim = this.get(key);
if (anim)
{
anim.load(child, startFrame);
}
return child;
};
module.exports = LoadAnimationToGameObject;

View file

@ -0,0 +1,23 @@
var PlayAnimation = function (key, child)
{
if (!Array.isArray(child))
{
child = [ child ];
}
var anim = this.get(key);
if (!anim)
{
return;
}
for (var i = 0; i < child.length; i++)
{
child[i].anims.play(key);
}
return this;
};
module.exports = PlayAnimation;

View file

@ -0,0 +1,13 @@
var RemoveAnimation = function (key)
{
var anim = this.get(key);
if (anim)
{
this.anims.delete(key);
}
return anim;
};
module.exports = RemoveAnimation;

View file

@ -0,0 +1,25 @@
var StaggerPlayAnimation = function (key, child, stagger)
{
if (stagger === undefined) { stagger = 0; }
if (!Array.isArray(child))
{
child = [ child ];
}
var anim = this.get(key);
if (!anim)
{
return;
}
for (var i = 0; i < child.length; i++)
{
child[i].anims.delayedPlay(stagger * i, key);
}
return this;
};
module.exports = StaggerPlayAnimation;

View file

@ -0,0 +1,23 @@
var ToJSON = function (key)
{
if (key !== undefined)
{
return this.anims.get(key).toJSON();
}
else
{
var output = {
anims: [],
globalTimeScale: this.globalTimeScale
};
this.anims.each(function (key, anim)
{
output.anims.push(anim.toJSON());
});
return output;
}
};
module.exports = ToJSON;

View file

@ -15,7 +15,7 @@ var MainLoop = require('./MainLoop');
var CreateRenderer = require('./CreateRenderer');
var GlobalInputManager = require('../input/GlobalInputManager');
var GlobalStateManager = require('../state/GlobalStateManager');
var AnimationManager = require('../animation/AnimationManager');
var AnimationManager = require('../animation/manager/AnimationManager');
var TextureManager = require('../textures/TextureManager');
var Data = require('../components/Data');
var Cache = require('../cache/Cache');

View file

@ -1,4 +1,4 @@
var CHECKSUM = {
build: '314dd020-1f74-11e7-b5ea-2d9635d37e06'
build: 'e7a0e0b0-1f7e-11e7-9f4f-1ff609af3206'
};
module.exports = CHECKSUM;

View file

@ -1,6 +1,6 @@
var Class = require('../utils/Class');
var Components = require('../animation/frame/');
var Components = require('../animation/frame/components/');
var Animation = new Class({