UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

1,065 lines (934 loc) 34.7 kB
/** * @author Richard Davey <rich@phaser.io> * @copyright 2013-2025 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var Animation = require('./Animation'); var Class = require('../utils/Class'); var CustomMap = require('../structs/Map'); var EventEmitter = require('eventemitter3'); var Events = require('./events'); var GameEvents = require('../core/events'); var GetFastValue = require('../utils/object/GetFastValue'); var GetValue = require('../utils/object/GetValue'); var MATH_CONST = require('../math/const'); var NumberArray = require('../utils/array/NumberArray'); var Pad = require('../utils/string/Pad'); /** * @classdesc * The Animation Manager. * * Animations are managed by the global Animation Manager. This is a singleton class that is * responsible for creating and delivering animations and their corresponding data to all Game Objects. * Unlike plugins it is owned by the Game instance, not the Scene. * * Sprites and other Game Objects get the data they need from the AnimationManager. * * @class AnimationManager * @extends Phaser.Events.EventEmitter * @memberof Phaser.Animations * @constructor * @since 3.0.0 * * @param {Phaser.Game} game - A reference to the Phaser.Game instance. */ var AnimationManager = new Class({ Extends: EventEmitter, initialize: function AnimationManager (game) { EventEmitter.call(this); /** * A reference to the Phaser.Game instance. * * @name Phaser.Animations.AnimationManager#game * @type {Phaser.Game} * @protected * @since 3.0.0 */ this.game = game; /** * A reference to the Texture Manager. * * @name Phaser.Animations.AnimationManager#textureManager * @type {Phaser.Textures.TextureManager} * @protected * @since 3.0.0 */ this.textureManager = null; /** * The global time scale of the Animation Manager. * * This scales the time delta between two frames, thus influencing the speed of time for the Animation Manager. * * @name Phaser.Animations.AnimationManager#globalTimeScale * @type {number} * @default 1 * @since 3.0.0 */ this.globalTimeScale = 1; /** * The Animations registered in the Animation Manager. * * This map should be modified with the {@link #add} and {@link #create} methods of the Animation Manager. * * @name Phaser.Animations.AnimationManager#anims * @type {Phaser.Structs.Map.<string, Phaser.Animations.Animation>} * @protected * @since 3.0.0 */ this.anims = new CustomMap(); /** * A list of animation mix times. * * See the {@link #setMix} method for more details. * * @name Phaser.Animations.AnimationManager#mixes * @type {Phaser.Structs.Map.<string, Phaser.Animations.Animation>} * @since 3.50.0 */ this.mixes = new CustomMap(); /** * Whether the Animation Manager is paused along with all of its Animations. * * @name Phaser.Animations.AnimationManager#paused * @type {boolean} * @default false * @since 3.0.0 */ this.paused = false; /** * The name of this Animation Manager. * * @name Phaser.Animations.AnimationManager#name * @type {string} * @since 3.0.0 */ this.name = 'AnimationManager'; game.events.once(GameEvents.BOOT, this.boot, this); }, /** * Registers event listeners after the Game boots. * * @method Phaser.Animations.AnimationManager#boot * @listens Phaser.Core.Events#DESTROY * @since 3.0.0 */ boot: function () { this.textureManager = this.game.textures; this.game.events.once(GameEvents.DESTROY, this.destroy, this); }, /** * Adds a mix between two animations. * * Mixing allows you to specify a unique delay between a pairing of animations. * * When playing Animation A on a Game Object, if you then play Animation B, and a * mix exists, it will wait for the specified delay to be over before playing Animation B. * * This allows you to customise smoothing between different types of animation, such * as blending between an idle and a walk state, or a running and a firing state. * * Note that mixing is only applied if you use the `Sprite.play` method. If you opt to use * `playAfterRepeat` or `playAfterDelay` instead, those will take priority and the mix * delay will not be used. * * To update an existing mix, just call this method with the new delay. * * To remove a mix pairing, see the `removeMix` method. * * @method Phaser.Animations.AnimationManager#addMix * @since 3.50.0 * * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. * @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B. * @param {number} delay - The delay, in milliseconds, to wait when transitioning from Animation A to B. * * @return {this} This Animation Manager. */ addMix: function (animA, animB, delay) { var anims = this.anims; var mixes = this.mixes; var keyA = (typeof(animA) === 'string') ? animA : animA.key; var keyB = (typeof(animB) === 'string') ? animB : animB.key; if (anims.has(keyA) && anims.has(keyB)) { var mixObj = mixes.get(keyA); if (!mixObj) { mixObj = {}; } mixObj[keyB] = delay; mixes.set(keyA, mixObj); } return this; }, /** * Removes a mix between two animations. * * Mixing allows you to specify a unique delay between a pairing of animations. * * Calling this method lets you remove those pairings. You can either remove * it between `animA` and `animB`, or if you do not provide the `animB` parameter, * it will remove all `animA` mixes. * * If you wish to update an existing mix instead, call the `addMix` method with the * new delay. * * @method Phaser.Animations.AnimationManager#removeMix * @since 3.50.0 * * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. * @param {(string|Phaser.Animations.Animation)} [animB] - The string-based key, or instance of, Animation B. If not given, all mixes for Animation A will be removed. * * @return {this} This Animation Manager. */ removeMix: function (animA, animB) { var mixes = this.mixes; var keyA = (typeof(animA) === 'string') ? animA : animA.key; var mixObj = mixes.get(keyA); if (mixObj) { if (animB) { var keyB = (typeof(animB) === 'string') ? animB : animB.key; if (mixObj.hasOwnProperty(keyB)) { // Remove just this pairing delete mixObj[keyB]; } } else if (!animB) { // Remove everything for animA mixes.delete(keyA); } } return this; }, /** * Returns the mix delay between two animations. * * If no mix has been set-up, this method will return zero. * * If you wish to create, or update, a new mix, call the `addMix` method. * If you wish to remove a mix, call the `removeMix` method. * * @method Phaser.Animations.AnimationManager#getMix * @since 3.50.0 * * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. * @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B. * * @return {number} The mix duration, or zero if no mix exists. */ getMix: function (animA, animB) { var mixes = this.mixes; var keyA = (typeof(animA) === 'string') ? animA : animA.key; var keyB = (typeof(animB) === 'string') ? animB : animB.key; var mixObj = mixes.get(keyA); if (mixObj && mixObj.hasOwnProperty(keyB)) { return mixObj[keyB]; } else { return 0; } }, /** * Adds an existing Animation to the Animation Manager. * * @method Phaser.Animations.AnimationManager#add * @fires Phaser.Animations.Events#ADD_ANIMATION * @since 3.0.0 * * @param {string} key - The key under which the Animation should be added. The Animation will be updated with it. Must be unique. * @param {Phaser.Animations.Animation} animation - The Animation which should be added to the Animation Manager. * * @return {this} This Animation Manager. */ add: function (key, animation) { if (this.anims.has(key)) { console.warn('Animation key exists: ' + key); return this; } animation.key = key; this.anims.set(key, animation); this.emit(Events.ADD_ANIMATION, key, animation); return this; }, /** * Checks to see if the given key is already in use within the Animation Manager or not. * * Animations are global. Keys created in one scene can be used from any other Scene in your game. They are not Scene specific. * * @method Phaser.Animations.AnimationManager#exists * @since 3.16.0 * * @param {string} key - The key of the Animation to check. * * @return {boolean} `true` if the Animation already exists in the Animation Manager, or `false` if the key is available. */ exists: function (key) { return this.anims.has(key); }, /** * Create one, or more animations from a loaded Aseprite JSON file. * * Aseprite is a powerful animated sprite editor and pixel art tool. * * You can find more details at https://www.aseprite.org/ * * To export a compatible JSON file in Aseprite, please do the following: * * 1. Go to "File - Export Sprite Sheet" * * 2. On the **Layout** tab: * 2a. Set the "Sheet type" to "Packed" * 2b. Set the "Constraints" to "None" * 2c. Check the "Merge Duplicates" checkbox * * 3. On the **Sprite** tab: * 3a. Set "Layers" to "Visible layers" * 3b. Set "Frames" to "All frames", unless you only wish to export a sub-set of tags * * 4. On the **Borders** tab: * 4a. Check the "Trim Sprite" and "Trim Cells" options * 4b. Ensure "Border Padding", "Spacing" and "Inner Padding" are all > 0 (1 is usually enough) * * 5. On the **Output** tab: * 5a. Check "Output File", give your image a name and make sure you choose "png files" as the file type * 5b. Check "JSON Data" and give your json file a name * 5c. The JSON Data type can be either a Hash or Array, Phaser doesn't mind. * 5d. Make sure "Tags" is checked in the Meta options * 5e. In the "Item Filename" input box, make sure it says just "{frame}" and nothing more. * * 6. Click export * * This was tested with Aseprite 1.2.25. * * This will export a png and json file which you can load using the Aseprite Loader, i.e.: * * ```javascript * function preload () * { * this.load.path = 'assets/animations/aseprite/'; * this.load.aseprite('paladin', 'paladin.png', 'paladin.json'); * } * ``` * * Once loaded, you can call this method from within a Scene with the 'atlas' key: * * ```javascript * this.anims.createFromAseprite('paladin'); * ``` * * Any animations defined in the JSON will now be available to use in Phaser and you play them * via their Tag name. For example, if you have an animation called 'War Cry' on your Aseprite timeline, * you can play it in Phaser using that Tag name: * * ```javascript * this.add.sprite(400, 300).play('War Cry'); * ``` * * When calling this method you can optionally provide an array of tag names, and only those animations * will be created. For example: * * ```javascript * this.anims.createFromAseprite('paladin', [ 'step', 'War Cry', 'Magnum Break' ]); * ``` * * This will only create the 3 animations defined. Note that the tag names are case-sensitive. * * @method Phaser.Animations.AnimationManager#createFromAseprite * @since 3.50.0 * * @param {string} key - The key of the loaded Aseprite atlas. It must have been loaded prior to calling this method. * @param {string[]} [tags] - An array of Tag names. If provided, only animations found in this array will be created. * @param {(Phaser.Animations.AnimationManager|Phaser.GameObjects.GameObject)} [target] - Create the animations on this target Sprite. If not given, they will be created globally in this Animation Manager. * * @return {Phaser.Animations.Animation[]} An array of Animation instances that were successfully created. */ createFromAseprite: function (key, tags, target) { var output = []; var data = this.game.cache.json.get(key); if (!data) { console.warn('No Aseprite data found for: ' + key); return output; } var _this = this; var meta = GetValue(data, 'meta', null); var frames = GetValue(data, 'frames', null); if (meta && frames) { var frameTags = GetValue(meta, 'frameTags', []); frameTags.forEach(function (tag) { var animFrames = []; var name = GetFastValue(tag, 'name', null); var from = GetFastValue(tag, 'from', 0); var to = GetFastValue(tag, 'to', 0); var direction = GetFastValue(tag, 'direction', 'forward'); if (!name) { // Skip if no name return; } if (!tags || (tags && tags.indexOf(name) > -1)) { // Get all the frames for this tag and calculate the total duration in milliseconds. var totalDuration = 0; for (var i = from; i <= to; i++) { var frameKey = i.toString(); var frame = frames[frameKey]; if (frame) { var frameDuration = GetFastValue(frame, 'duration', MATH_CONST.MAX_SAFE_INTEGER); animFrames.push({ key: key, frame: frameKey, duration: frameDuration }); totalDuration += frameDuration; } } if (direction === 'reverse') { animFrames = animFrames.reverse(); } // Create the animation var createConfig = { key: name, frames: animFrames, duration: totalDuration, yoyo: (direction === 'pingpong') }; var result; if (target) { if (target.anims) { result = target.anims.create(createConfig); } } else { result = _this.create(createConfig); } if (result) { output.push(result); } } }); } return output; }, /** * Creates a new Animation and adds it to the Animation Manager. * * Animations are global. Once created, you can use them in any Scene in your game. They are not Scene specific. * * If an invalid key is given this method will return `false`. * * If you pass the key of an animation that already exists in the Animation Manager, that animation will be returned. * * A brand new animation is only created if the key is valid and not already in use. * * If you wish to re-use an existing key, call `AnimationManager.remove` first, then this method. * * @method Phaser.Animations.AnimationManager#create * @fires Phaser.Animations.Events#ADD_ANIMATION * @since 3.0.0 * * @param {Phaser.Types.Animations.Animation} config - The configuration settings for the Animation. * * @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` if the key is already in use. */ create: function (config) { var key = config.key; var anim = false; if (key) { anim = this.get(key); if (!anim) { anim = new Animation(this, key, config); this.anims.set(key, anim); this.emit(Events.ADD_ANIMATION, key, anim); } else { console.warn('AnimationManager key already exists: ' + key); } } return anim; }, /** * Loads this Animation Manager's Animations and settings from a JSON object. * * @method Phaser.Animations.AnimationManager#fromJSON * @since 3.0.0 * * @param {(string|Phaser.Types.Animations.JSONAnimations|Phaser.Types.Animations.JSONAnimation)} data - The JSON object to parse. * @param {boolean} [clearCurrentAnimations=false] - If set to `true`, the current animations will be removed (`anims.clear()`). If set to `false` (default), the animations in `data` will be added. * * @return {Phaser.Animations.Animation[]} An array containing all of the Animation objects that were created as a result of this call. */ fromJSON: function (data, clearCurrentAnimations) { if (clearCurrentAnimations === undefined) { clearCurrentAnimations = false; } if (clearCurrentAnimations) { this.anims.clear(); } // Do we have a String (i.e. from JSON, or an Object?) if (typeof data === 'string') { data = JSON.parse(data); } var output = []; // Array of animations, or a single animation? if (data.hasOwnProperty('anims') && Array.isArray(data.anims)) { for (var i = 0; i < data.anims.length; i++) { output.push(this.create(data.anims[i])); } if (data.hasOwnProperty('globalTimeScale')) { this.globalTimeScale = data.globalTimeScale; } } else if (data.hasOwnProperty('key') && data.type === 'frame') { output.push(this.create(data)); } return output; }, /** * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. * * Generates objects with string based frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNames}. * * It's a helper method, designed to make it easier for you to extract all of the frame names from texture atlases. * * If you're working with a sprite sheet, see the `generateFrameNumbers` method instead. * * Example: * * If you have a texture atlases loaded called `gems` and it contains 6 frames called `ruby_0001`, `ruby_0002`, and so on, * then you can call this method using: `this.anims.generateFrameNames('gems', { prefix: 'ruby_', start: 1, end: 6, zeroPad: 4 })`. * * The `end` value tells it to select frames 1 through 6, incrementally numbered, all starting with the prefix `ruby_`. The `zeroPad` * value tells it how many zeroes pad out the numbers. To create an animation using this method, you can do: * * ```javascript * this.anims.create({ * key: 'ruby', * repeat: -1, * frames: this.anims.generateFrameNames('gems', { * prefix: 'ruby_', * end: 6, * zeroPad: 4 * }) * }); * ``` * * Please see the animation examples for further details. * * @method Phaser.Animations.AnimationManager#generateFrameNames * @since 3.0.0 * * @param {string} key - The key for the texture containing the animation frames. * @param {Phaser.Types.Animations.GenerateFrameNames} [config] - The configuration object for the animation frame names. * * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. */ generateFrameNames: function (key, config) { var prefix = GetValue(config, 'prefix', ''); var start = GetValue(config, 'start', 0); var end = GetValue(config, 'end', 0); var suffix = GetValue(config, 'suffix', ''); var zeroPad = GetValue(config, 'zeroPad', 0); var out = GetValue(config, 'outputArray', []); var frames = GetValue(config, 'frames', false); if (!this.textureManager.exists(key)) { console.warn('Texture "%s" not found', key); return out; } var texture = this.textureManager.get(key); if (!texture) { return out; } var i; if (!config) { // Use every frame in the atlas frames = texture.getFrameNames(); for (i = 0; i < frames.length; i++) { out.push({ key: key, frame: frames[i] }); } } else { if (!frames) { frames = NumberArray(start, end); } for (i = 0; i < frames.length; i++) { var frame = prefix + Pad(frames[i], zeroPad, '0', 1) + suffix; if (texture.has(frame)) { out.push({ key: key, frame: frame }); } else { console.warn('Frame "%s" not found in texture "%s"', frame, key); } } } return out; }, /** * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. * * Generates objects with numbered frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNumbers}. * * If you're working with a texture atlas, see the `generateFrameNames` method instead. * * It's a helper method, designed to make it easier for you to extract frames from sprite sheets. * * Example: * * If you have a sprite sheet loaded called `explosion` and it contains 12 frames, then you can call this method using: * * `this.anims.generateFrameNumbers('explosion', { start: 0, end: 11 })`. * * The `end` value of 11 tells it to stop after the 12th frame has been added, because it started at zero. * * To create an animation using this method, you can do: * * ```javascript * this.anims.create({ * key: 'boom', * frames: this.anims.generateFrameNumbers('explosion', { * start: 0, * end: 11 * }) * }); * ``` * * Note that `start` is optional and you don't need to include it if the animation starts from frame 0. * * To specify an animation in reverse, swap the `start` and `end` values. * * If the frames are not sequential, you may pass an array of frame numbers instead, for example: * * `this.anims.generateFrameNumbers('explosion', { frames: [ 0, 1, 2, 1, 2, 3, 4, 0, 1, 2 ] })` * * Please see the animation examples and `GenerateFrameNumbers` config docs for further details. * * @method Phaser.Animations.AnimationManager#generateFrameNumbers * @since 3.0.0 * * @param {string} key - The key for the texture containing the animation frames. * @param {Phaser.Types.Animations.GenerateFrameNumbers} [config] - The configuration object for the animation frames. * * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. */ generateFrameNumbers: function (key, config) { var start = GetValue(config, 'start', 0); var end = GetValue(config, 'end', -1); var first = GetValue(config, 'first', false); var out = GetValue(config, 'outputArray', []); var frames = GetValue(config, 'frames', false); if (!this.textureManager.exists(key)) { console.warn('Texture "%s" not found', key); return out; } var texture = this.textureManager.get(key); if (!texture) { return out; } if (first && texture.has(first)) { out.push({ key: key, frame: first }); } // No 'frames' array? Then generate one automatically if (!frames) { if (end === -1) { // -1 because of __BASE, which we don't want in our results // and -1 because frames are zero based end = texture.frameTotal - 2; } frames = NumberArray(start, end); } for (var i = 0; i < frames.length; i++) { var frameName = frames[i]; if (texture.has(frameName)) { out.push({ key: key, frame: frameName }); } else { console.warn('Frame "%s" not found in texture "%s"', frameName, key); } } return out; }, /** * Get an Animation. * * @method Phaser.Animations.AnimationManager#get * @since 3.0.0 * * @param {string} key - The key of the Animation to retrieve. * * @return {Phaser.Animations.Animation} The Animation. */ get: function (key) { return this.anims.get(key); }, /** * Returns an array of all Animation keys that are using the given * Texture. Only Animations that have at least one AnimationFrame * entry using this texture will be included in the result. * * @method Phaser.Animations.AnimationManager#getAnimsFromTexture * @since 3.60.0 * * @param {(string|Phaser.Textures.Texture|Phaser.Textures.Frame)} key - The unique string-based key of the Texture, or a Texture, or Frame instance. * * @return {string[]} An array of Animation keys that feature the given Texture. */ getAnimsFromTexture: function (key) { var texture = this.textureManager.get(key); var match = texture.key; var anims = this.anims.getArray(); var out = []; for (var i = 0; i < anims.length; i++) { var anim = anims[i]; var frames = anim.frames; for (var c = 0; c < frames.length; c++) { if (frames[c].textureKey === match) { out.push(anim.key); break; } } } return out; }, /** * Pause all animations. * * @method Phaser.Animations.AnimationManager#pauseAll * @fires Phaser.Animations.Events#PAUSE_ALL * @since 3.0.0 * * @return {this} This Animation Manager. */ pauseAll: function () { if (!this.paused) { this.paused = true; this.emit(Events.PAUSE_ALL); } return this; }, /** * Play an animation on the given Game Objects that have an Animation Component. * * @method Phaser.Animations.AnimationManager#play * @since 3.0.0 * * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component. * * @return {this} This Animation Manager. */ play: function (key, children) { if (!Array.isArray(children)) { children = [ children ]; } for (var i = 0; i < children.length; i++) { children[i].anims.play(key); } return this; }, /** * Takes an array of Game Objects that have an Animation Component and then * starts the given animation playing on them. The start time of each Game Object * is offset, incrementally, by the `stagger` amount. * * For example, if you pass an array with 4 children and a stagger time of 1000, * the delays will be: * * child 1: 1000ms delay * child 2: 2000ms delay * child 3: 3000ms delay * child 4: 4000ms delay * * If you set the `staggerFirst` parameter to `false` they would be: * * child 1: 0ms delay * child 2: 1000ms delay * child 3: 2000ms delay * child 4: 3000ms delay * * You can also set `stagger` to be a negative value. If it was -1000, the above would be: * * child 1: 3000ms delay * child 2: 2000ms delay * child 3: 1000ms delay * child 4: 0ms delay * * @method Phaser.Animations.AnimationManager#staggerPlay * @since 3.0.0 * * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] * * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component. * @param {number} stagger - The amount of time, in milliseconds, to offset each play time by. If a negative value is given, it's applied to the children in reverse order. * @param {boolean} [staggerFirst=true] -Should the first child be staggered as well? * * @return {this} This Animation Manager. */ staggerPlay: function (key, children, stagger, staggerFirst) { if (stagger === undefined) { stagger = 0; } if (staggerFirst === undefined) { staggerFirst = true; } if (!Array.isArray(children)) { children = [ children ]; } var len = children.length; if (!staggerFirst) { len--; } for (var i = 0; i < children.length; i++) { var time = (stagger < 0) ? Math.abs(stagger) * (len - i) : stagger * i; children[i].anims.playAfterDelay(key, time); } return this; }, /** * Removes an Animation from this Animation Manager, based on the given key. * * This is a global action. Once an Animation has been removed, no Game Objects * can carry on using it. * * @method Phaser.Animations.AnimationManager#remove * @fires Phaser.Animations.Events#REMOVE_ANIMATION * @since 3.0.0 * * @param {string} key - The key of the animation to remove. * * @return {Phaser.Animations.Animation} The Animation instance that was removed from the Animation Manager. */ remove: function (key) { var anim = this.get(key); if (anim) { this.emit(Events.REMOVE_ANIMATION, key, anim); this.anims.delete(key); this.removeMix(key); } return anim; }, /** * Resume all paused animations. * * @method Phaser.Animations.AnimationManager#resumeAll * @fires Phaser.Animations.Events#RESUME_ALL * @since 3.0.0 * * @return {this} This Animation Manager. */ resumeAll: function () { if (this.paused) { this.paused = false; this.emit(Events.RESUME_ALL); } return this; }, /** * Returns the Animation data as JavaScript object based on the given key. * Or, if not key is defined, it will return the data of all animations as array of objects. * * @method Phaser.Animations.AnimationManager#toJSON * @since 3.0.0 * * @param {string} [key] - The animation to get the JSONAnimation data from. If not provided, all animations are returned as an array. * * @return {Phaser.Types.Animations.JSONAnimations} The resulting JSONAnimations formatted object. */ toJSON: function (key) { var output = { anims: [], globalTimeScale: this.globalTimeScale }; if (key !== undefined && key !== '') { output.anims.push(this.anims.get(key).toJSON()); } else { this.anims.each(function (animationKey, animation) { output.anims.push(animation.toJSON()); }); } return output; }, /** * Destroy this Animation Manager and clean up animation definitions and references to other objects. * This method should not be called directly. It will be called automatically as a response to a `destroy` event from the Phaser.Game instance. * * @method Phaser.Animations.AnimationManager#destroy * @since 3.0.0 */ destroy: function () { this.anims.clear(); this.mixes.clear(); this.textureManager = null; this.game = null; } }); module.exports = AnimationManager;