diff --git a/src/core/ticker/index.js b/src/core/ticker/index.js index f68c3b3..4b3017c 100644 --- a/src/core/ticker/index.js +++ b/src/core/ticker/index.js @@ -1,7 +1,7 @@ import Ticker from './Ticker'; /** - * The shared ticker instance used by {@link PIXI.extras.MovieClip}. + * The shared ticker instance used by {@link PIXI.extras.AnimatedSprite}. * and by {@link PIXI.interaction.InteractionManager}. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true` * for this instance. Please follow the examples for usage, including diff --git a/src/core/ticker/index.js b/src/core/ticker/index.js index f68c3b3..4b3017c 100644 --- a/src/core/ticker/index.js +++ b/src/core/ticker/index.js @@ -1,7 +1,7 @@ import Ticker from './Ticker'; /** - * The shared ticker instance used by {@link PIXI.extras.MovieClip}. + * The shared ticker instance used by {@link PIXI.extras.AnimatedSprite}. * and by {@link PIXI.interaction.InteractionManager}. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true` * for this instance. Please follow the examples for usage, including diff --git a/src/deprecation.js b/src/deprecation.js index 9d63a5e..158a13c 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -177,9 +177,9 @@ enumerable: true, get() { - warn('The MovieClip class has been moved to extras.MovieClip, please use extras.MovieClip from now on.'); + warn('The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.'); - return extras.MovieClip; + return extras.AnimatedSprite; }, }, @@ -348,6 +348,26 @@ }, }); +Object.defineProperties(extras, { + + /** + * @class + * @name MovieClip + * @memberof PIXI.extras + * @see PIXI.extras.AnimatedSprite + * @deprecated since version 4.2.0 + */ + MovieClip: { + enumerable: true, + get() + { + warn('The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.'); + + return extras.AnimatedSprite; + }, + }, +}); + core.DisplayObject.prototype.generateTexture = function generateTexture(renderer, scaleMode, resolution) { warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); diff --git a/src/core/ticker/index.js b/src/core/ticker/index.js index f68c3b3..4b3017c 100644 --- a/src/core/ticker/index.js +++ b/src/core/ticker/index.js @@ -1,7 +1,7 @@ import Ticker from './Ticker'; /** - * The shared ticker instance used by {@link PIXI.extras.MovieClip}. + * The shared ticker instance used by {@link PIXI.extras.AnimatedSprite}. * and by {@link PIXI.interaction.InteractionManager}. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true` * for this instance. Please follow the examples for usage, including diff --git a/src/deprecation.js b/src/deprecation.js index 9d63a5e..158a13c 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -177,9 +177,9 @@ enumerable: true, get() { - warn('The MovieClip class has been moved to extras.MovieClip, please use extras.MovieClip from now on.'); + warn('The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.'); - return extras.MovieClip; + return extras.AnimatedSprite; }, }, @@ -348,6 +348,26 @@ }, }); +Object.defineProperties(extras, { + + /** + * @class + * @name MovieClip + * @memberof PIXI.extras + * @see PIXI.extras.AnimatedSprite + * @deprecated since version 4.2.0 + */ + MovieClip: { + enumerable: true, + get() + { + warn('The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.'); + + return extras.AnimatedSprite; + }, + }, +}); + core.DisplayObject.prototype.generateTexture = function generateTexture(renderer, scaleMode, resolution) { warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js new file mode 100644 index 0000000..e9a9486 --- /dev/null +++ b/src/extras/AnimatedSprite.js @@ -0,0 +1,365 @@ +import * as core from '../core'; + +/** + * @typedef FrameObject + * @type {object} + * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame + * @property {number} time - the duration of the frame in ms + */ + +/** + * A AnimatedSprite is a simple way to display an animation depicted by a list of textures. + * + * ```js + * let alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"]; + * let textureArray = []; + * + * for (let i=0; i < 4; i++) + * { + * let texture = PIXI.Texture.fromImage(alienImages[i]); + * textureArray.push(texture); + * }; + * + * let mc = new PIXI.AnimatedSprite(textureArray); + * ``` + * + * @class + * @extends PIXI.Sprite + * @memberof PIXI.extras + */ +export default class AnimatedSprite extends core.Sprite +{ + /** + * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * objects that make up the animation + */ + constructor(textures) + { + super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); + + /** + * @private + */ + this._textures = null; + + /** + * @private + */ + this._durations = null; + + this.textures = textures; + + /** + * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower + * + * @member {number} + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @member {boolean} + * @default true + */ + this.loop = true; + + /** + * Function to call when a AnimatedSprite finishes playing + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onComplete = null; + + /** + * Function to call when a AnimatedSprite changes which texture is being rendered + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onFrameChange = null; + + /** + * Elapsed time since animation has been started, used internally to display current texture + * + * @member {number} + * @private + */ + this._currentTime = 0; + + /** + * Indicates if the AnimatedSprite is currently playing + * + * @member {boolean} + * @readonly + */ + this.playing = false; + } + + /** + * Stops the AnimatedSprite + * + */ + stop() + { + if (!this.playing) + { + return; + } + + this.playing = false; + core.ticker.shared.remove(this.update, this); + } + + /** + * Plays the AnimatedSprite + * + */ + play() + { + if (this.playing) + { + return; + } + + this.playing = true; + core.ticker.shared.add(this.update, this); + } + + /** + * Stops the AnimatedSprite and goes to a specific frame + * + * @param {number} frameNumber - frame index to stop at + */ + gotoAndStop(frameNumber) + { + this.stop(); + + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Goes to a specific frame and begins playing the AnimatedSprite + * + * @param {number} frameNumber - frame index to start at + */ + gotoAndPlay(frameNumber) + { + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + + this.play(); + } + + /** + * Updates the object transform for rendering. + * + * @private + * @param {number} deltaTime - Time since last tick. + */ + update(deltaTime) + { + const elapsed = this.animationSpeed * deltaTime; + const previousFrame = this.currentFrame; + + if (this._durations !== null) + { + let lag = this._currentTime % 1 * this._durations[this.currentFrame]; + + lag += elapsed / 60 * 1000; + + while (lag < 0) + { + this._currentTime--; + lag += this._durations[this.currentFrame]; + } + + const sign = Math.sign(this.animationSpeed * deltaTime); + + this._currentTime = Math.floor(this._currentTime); + + while (lag >= this._durations[this.currentFrame]) + { + lag -= this._durations[this.currentFrame] * sign; + this._currentTime += sign; + } + + this._currentTime += lag / this._durations[this.currentFrame]; + } + else + { + this._currentTime += elapsed; + } + + if (this._currentTime < 0 && !this.loop) + { + this.gotoAndStop(0); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (this._currentTime >= this._textures.length && !this.loop) + { + this.gotoAndStop(this._textures.length - 1); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Updates the displayed texture to match the current frame index + * + * @private + */ + updateTexture() + { + this._texture = this._textures[this.currentFrame]; + this._textureID = -1; + + if (this.onFrameChange) + { + this.onFrameChange(this.currentFrame); + } + } + + /** + * Stops the AnimatedSprite and destroys it + * + */ + destroy() + { + this.stop(); + super.destroy(); + } + + /** + * A short hand way of creating a movieclip from an array of frame ids + * + * @static + * @param {string[]} frames - The array of frames ids the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified frames. + */ + static fromFrames(frames) + { + const textures = []; + + for (let i = 0; i < frames.length; ++i) + { + textures.push(core.Texture.fromFrame(frames[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * A short hand way of creating a movieclip from an array of image ids + * + * @static + * @param {string[]} images - the array of image urls the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified images as frames. + */ + static fromImages(images) + { + const textures = []; + + for (let i = 0; i < images.length; ++i) + { + textures.push(core.Texture.fromImage(images[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * totalFrames is the total number of frames in the AnimatedSprite. This is the same as number of textures + * assigned to the AnimatedSprite. + * + * @readonly + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @default 0 + */ + get totalFrames() + { + return this._textures.length; + } + + /** + * The array of textures used for this AnimatedSprite + * + * @member {PIXI.Texture[]} + * @memberof PIXI.extras.AnimatedSprite# + */ + get textures() + { + return this._textures; + } + + /** + * Sets the textures. + * + * @param {PIXI.Texture[]} value - The texture to set. + */ + set textures(value) + { + if (value[0] instanceof core.Texture) + { + this._textures = value; + this._durations = null; + } + else + { + this._textures = []; + this._durations = []; + + for (let i = 0; i < value.length; i++) + { + this._textures.push(value[i].texture); + this._durations.push(value[i].time); + } + } + } + + /** + * The AnimatedSprites current frame index + * + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @readonly + */ + get currentFrame() + { + let currentFrame = Math.floor(this._currentTime) % this._textures.length; + + if (currentFrame < 0) + { + currentFrame += this._textures.length; + } + + return currentFrame; + } +} diff --git a/src/core/ticker/index.js b/src/core/ticker/index.js index f68c3b3..4b3017c 100644 --- a/src/core/ticker/index.js +++ b/src/core/ticker/index.js @@ -1,7 +1,7 @@ import Ticker from './Ticker'; /** - * The shared ticker instance used by {@link PIXI.extras.MovieClip}. + * The shared ticker instance used by {@link PIXI.extras.AnimatedSprite}. * and by {@link PIXI.interaction.InteractionManager}. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true` * for this instance. Please follow the examples for usage, including diff --git a/src/deprecation.js b/src/deprecation.js index 9d63a5e..158a13c 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -177,9 +177,9 @@ enumerable: true, get() { - warn('The MovieClip class has been moved to extras.MovieClip, please use extras.MovieClip from now on.'); + warn('The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.'); - return extras.MovieClip; + return extras.AnimatedSprite; }, }, @@ -348,6 +348,26 @@ }, }); +Object.defineProperties(extras, { + + /** + * @class + * @name MovieClip + * @memberof PIXI.extras + * @see PIXI.extras.AnimatedSprite + * @deprecated since version 4.2.0 + */ + MovieClip: { + enumerable: true, + get() + { + warn('The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.'); + + return extras.AnimatedSprite; + }, + }, +}); + core.DisplayObject.prototype.generateTexture = function generateTexture(renderer, scaleMode, resolution) { warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js new file mode 100644 index 0000000..e9a9486 --- /dev/null +++ b/src/extras/AnimatedSprite.js @@ -0,0 +1,365 @@ +import * as core from '../core'; + +/** + * @typedef FrameObject + * @type {object} + * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame + * @property {number} time - the duration of the frame in ms + */ + +/** + * A AnimatedSprite is a simple way to display an animation depicted by a list of textures. + * + * ```js + * let alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"]; + * let textureArray = []; + * + * for (let i=0; i < 4; i++) + * { + * let texture = PIXI.Texture.fromImage(alienImages[i]); + * textureArray.push(texture); + * }; + * + * let mc = new PIXI.AnimatedSprite(textureArray); + * ``` + * + * @class + * @extends PIXI.Sprite + * @memberof PIXI.extras + */ +export default class AnimatedSprite extends core.Sprite +{ + /** + * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * objects that make up the animation + */ + constructor(textures) + { + super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); + + /** + * @private + */ + this._textures = null; + + /** + * @private + */ + this._durations = null; + + this.textures = textures; + + /** + * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower + * + * @member {number} + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @member {boolean} + * @default true + */ + this.loop = true; + + /** + * Function to call when a AnimatedSprite finishes playing + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onComplete = null; + + /** + * Function to call when a AnimatedSprite changes which texture is being rendered + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onFrameChange = null; + + /** + * Elapsed time since animation has been started, used internally to display current texture + * + * @member {number} + * @private + */ + this._currentTime = 0; + + /** + * Indicates if the AnimatedSprite is currently playing + * + * @member {boolean} + * @readonly + */ + this.playing = false; + } + + /** + * Stops the AnimatedSprite + * + */ + stop() + { + if (!this.playing) + { + return; + } + + this.playing = false; + core.ticker.shared.remove(this.update, this); + } + + /** + * Plays the AnimatedSprite + * + */ + play() + { + if (this.playing) + { + return; + } + + this.playing = true; + core.ticker.shared.add(this.update, this); + } + + /** + * Stops the AnimatedSprite and goes to a specific frame + * + * @param {number} frameNumber - frame index to stop at + */ + gotoAndStop(frameNumber) + { + this.stop(); + + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Goes to a specific frame and begins playing the AnimatedSprite + * + * @param {number} frameNumber - frame index to start at + */ + gotoAndPlay(frameNumber) + { + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + + this.play(); + } + + /** + * Updates the object transform for rendering. + * + * @private + * @param {number} deltaTime - Time since last tick. + */ + update(deltaTime) + { + const elapsed = this.animationSpeed * deltaTime; + const previousFrame = this.currentFrame; + + if (this._durations !== null) + { + let lag = this._currentTime % 1 * this._durations[this.currentFrame]; + + lag += elapsed / 60 * 1000; + + while (lag < 0) + { + this._currentTime--; + lag += this._durations[this.currentFrame]; + } + + const sign = Math.sign(this.animationSpeed * deltaTime); + + this._currentTime = Math.floor(this._currentTime); + + while (lag >= this._durations[this.currentFrame]) + { + lag -= this._durations[this.currentFrame] * sign; + this._currentTime += sign; + } + + this._currentTime += lag / this._durations[this.currentFrame]; + } + else + { + this._currentTime += elapsed; + } + + if (this._currentTime < 0 && !this.loop) + { + this.gotoAndStop(0); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (this._currentTime >= this._textures.length && !this.loop) + { + this.gotoAndStop(this._textures.length - 1); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Updates the displayed texture to match the current frame index + * + * @private + */ + updateTexture() + { + this._texture = this._textures[this.currentFrame]; + this._textureID = -1; + + if (this.onFrameChange) + { + this.onFrameChange(this.currentFrame); + } + } + + /** + * Stops the AnimatedSprite and destroys it + * + */ + destroy() + { + this.stop(); + super.destroy(); + } + + /** + * A short hand way of creating a movieclip from an array of frame ids + * + * @static + * @param {string[]} frames - The array of frames ids the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified frames. + */ + static fromFrames(frames) + { + const textures = []; + + for (let i = 0; i < frames.length; ++i) + { + textures.push(core.Texture.fromFrame(frames[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * A short hand way of creating a movieclip from an array of image ids + * + * @static + * @param {string[]} images - the array of image urls the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified images as frames. + */ + static fromImages(images) + { + const textures = []; + + for (let i = 0; i < images.length; ++i) + { + textures.push(core.Texture.fromImage(images[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * totalFrames is the total number of frames in the AnimatedSprite. This is the same as number of textures + * assigned to the AnimatedSprite. + * + * @readonly + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @default 0 + */ + get totalFrames() + { + return this._textures.length; + } + + /** + * The array of textures used for this AnimatedSprite + * + * @member {PIXI.Texture[]} + * @memberof PIXI.extras.AnimatedSprite# + */ + get textures() + { + return this._textures; + } + + /** + * Sets the textures. + * + * @param {PIXI.Texture[]} value - The texture to set. + */ + set textures(value) + { + if (value[0] instanceof core.Texture) + { + this._textures = value; + this._durations = null; + } + else + { + this._textures = []; + this._durations = []; + + for (let i = 0; i < value.length; i++) + { + this._textures.push(value[i].texture); + this._durations.push(value[i].time); + } + } + } + + /** + * The AnimatedSprites current frame index + * + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @readonly + */ + get currentFrame() + { + let currentFrame = Math.floor(this._currentTime) % this._textures.length; + + if (currentFrame < 0) + { + currentFrame += this._textures.length; + } + + return currentFrame; + } +} diff --git a/src/extras/MovieClip.js b/src/extras/MovieClip.js deleted file mode 100644 index 5dc83e9..0000000 --- a/src/extras/MovieClip.js +++ /dev/null @@ -1,365 +0,0 @@ -import * as core from '../core'; - -/** - * @typedef FrameObject - * @type {object} - * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame - * @property {number} time - the duration of the frame in ms - */ - -/** - * A MovieClip is a simple way to display an animation depicted by a list of textures. - * - * ```js - * let alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"]; - * let textureArray = []; - * - * for (let i=0; i < 4; i++) - * { - * let texture = PIXI.Texture.fromImage(alienImages[i]); - * textureArray.push(texture); - * }; - * - * let mc = new PIXI.MovieClip(textureArray); - * ``` - * - * @class - * @extends PIXI.Sprite - * @memberof PIXI.extras - */ -export default class MovieClip extends core.Sprite -{ - /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame - * objects that make up the animation - */ - constructor(textures) - { - super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); - - /** - * @private - */ - this._textures = null; - - /** - * @private - */ - this._durations = null; - - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @member {number} - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @member {boolean} - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @method - * @memberof PIXI.extras.MovieClip# - */ - this.onComplete = null; - - /** - * Function to call when a MovieClip changes which texture is being rendered - * - * @method - * @memberof PIXI.extras.MovieClip# - */ - this.onFrameChange = null; - - /** - * Elapsed time since animation has been started, used internally to display current texture - * - * @member {number} - * @private - */ - this._currentTime = 0; - - /** - * Indicates if the MovieClip is currently playing - * - * @member {boolean} - * @readonly - */ - this.playing = false; - } - - /** - * Stops the MovieClip - * - */ - stop() - { - if (!this.playing) - { - return; - } - - this.playing = false; - core.ticker.shared.remove(this.update, this); - } - - /** - * Plays the MovieClip - * - */ - play() - { - if (this.playing) - { - return; - } - - this.playing = true; - core.ticker.shared.add(this.update, this); - } - - /** - * Stops the MovieClip and goes to a specific frame - * - * @param {number} frameNumber - frame index to stop at - */ - gotoAndStop(frameNumber) - { - this.stop(); - - const previousFrame = this.currentFrame; - - this._currentTime = frameNumber; - - if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - } - - /** - * Goes to a specific frame and begins playing the MovieClip - * - * @param {number} frameNumber - frame index to start at - */ - gotoAndPlay(frameNumber) - { - const previousFrame = this.currentFrame; - - this._currentTime = frameNumber; - - if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - - this.play(); - } - - /** - * Updates the object transform for rendering. - * - * @private - * @param {number} deltaTime - Time since last tick. - */ - update(deltaTime) - { - const elapsed = this.animationSpeed * deltaTime; - const previousFrame = this.currentFrame; - - if (this._durations !== null) - { - let lag = this._currentTime % 1 * this._durations[this.currentFrame]; - - lag += elapsed / 60 * 1000; - - while (lag < 0) - { - this._currentTime--; - lag += this._durations[this.currentFrame]; - } - - const sign = Math.sign(this.animationSpeed * deltaTime); - - this._currentTime = Math.floor(this._currentTime); - - while (lag >= this._durations[this.currentFrame]) - { - lag -= this._durations[this.currentFrame] * sign; - this._currentTime += sign; - } - - this._currentTime += lag / this._durations[this.currentFrame]; - } - else - { - this._currentTime += elapsed; - } - - if (this._currentTime < 0 && !this.loop) - { - this.gotoAndStop(0); - - if (this.onComplete) - { - this.onComplete(); - } - } - else if (this._currentTime >= this._textures.length && !this.loop) - { - this.gotoAndStop(this._textures.length - 1); - - if (this.onComplete) - { - this.onComplete(); - } - } - else if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - } - - /** - * Updates the displayed texture to match the current frame index - * - * @private - */ - updateTexture() - { - this._texture = this._textures[this.currentFrame]; - this._textureID = -1; - - if (this.onFrameChange) - { - this.onFrameChange(this.currentFrame); - } - } - - /** - * Stops the MovieClip and destroys it - * - */ - destroy() - { - this.stop(); - super.destroy(); - } - - /** - * A short hand way of creating a movieclip from an array of frame ids - * - * @static - * @param {string[]} frames - The array of frames ids the movieclip will use as its texture frames - * @return {MovieClip} The new movie clip with the specified frames. - */ - static fromFrames(frames) - { - const textures = []; - - for (let i = 0; i < frames.length; ++i) - { - textures.push(core.Texture.fromFrame(frames[i])); - } - - return new MovieClip(textures); - } - - /** - * A short hand way of creating a movieclip from an array of image ids - * - * @static - * @param {string[]} images - the array of image urls the movieclip will use as its texture frames - * @return {MovieClip} The new movie clip with the specified images as frames. - */ - static fromImages(images) - { - const textures = []; - - for (let i = 0; i < images.length; ++i) - { - textures.push(core.Texture.fromImage(images[i])); - } - - return new MovieClip(textures); - } - - /** - * totalFrames is the total number of frames in the MovieClip. This is the same as number of textures - * assigned to the MovieClip. - * - * @readonly - * @member {number} - * @memberof PIXI.extras.MovieClip# - * @default 0 - */ - get totalFrames() - { - return this._textures.length; - } - - /** - * The array of textures used for this MovieClip - * - * @member {PIXI.Texture[]} - * @memberof PIXI.extras.MovieClip# - */ - get textures() - { - return this._textures; - } - - /** - * Sets the textures. - * - * @param {PIXI.Texture[]} value - The texture to set. - */ - set textures(value) - { - if (value[0] instanceof core.Texture) - { - this._textures = value; - this._durations = null; - } - else - { - this._textures = []; - this._durations = []; - - for (let i = 0; i < value.length; i++) - { - this._textures.push(value[i].texture); - this._durations.push(value[i].time); - } - } - } - - /** - * The MovieClips current frame index - * - * @member {number} - * @memberof PIXI.extras.MovieClip# - * @readonly - */ - get currentFrame() - { - let currentFrame = Math.floor(this._currentTime) % this._textures.length; - - if (currentFrame < 0) - { - currentFrame += this._textures.length; - } - - return currentFrame; - } -} diff --git a/src/core/ticker/index.js b/src/core/ticker/index.js index f68c3b3..4b3017c 100644 --- a/src/core/ticker/index.js +++ b/src/core/ticker/index.js @@ -1,7 +1,7 @@ import Ticker from './Ticker'; /** - * The shared ticker instance used by {@link PIXI.extras.MovieClip}. + * The shared ticker instance used by {@link PIXI.extras.AnimatedSprite}. * and by {@link PIXI.interaction.InteractionManager}. * The property {@link PIXI.ticker.Ticker#autoStart} is set to `true` * for this instance. Please follow the examples for usage, including diff --git a/src/deprecation.js b/src/deprecation.js index 9d63a5e..158a13c 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -177,9 +177,9 @@ enumerable: true, get() { - warn('The MovieClip class has been moved to extras.MovieClip, please use extras.MovieClip from now on.'); + warn('The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.'); - return extras.MovieClip; + return extras.AnimatedSprite; }, }, @@ -348,6 +348,26 @@ }, }); +Object.defineProperties(extras, { + + /** + * @class + * @name MovieClip + * @memberof PIXI.extras + * @see PIXI.extras.AnimatedSprite + * @deprecated since version 4.2.0 + */ + MovieClip: { + enumerable: true, + get() + { + warn('The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.'); + + return extras.AnimatedSprite; + }, + }, +}); + core.DisplayObject.prototype.generateTexture = function generateTexture(renderer, scaleMode, resolution) { warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js new file mode 100644 index 0000000..e9a9486 --- /dev/null +++ b/src/extras/AnimatedSprite.js @@ -0,0 +1,365 @@ +import * as core from '../core'; + +/** + * @typedef FrameObject + * @type {object} + * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame + * @property {number} time - the duration of the frame in ms + */ + +/** + * A AnimatedSprite is a simple way to display an animation depicted by a list of textures. + * + * ```js + * let alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"]; + * let textureArray = []; + * + * for (let i=0; i < 4; i++) + * { + * let texture = PIXI.Texture.fromImage(alienImages[i]); + * textureArray.push(texture); + * }; + * + * let mc = new PIXI.AnimatedSprite(textureArray); + * ``` + * + * @class + * @extends PIXI.Sprite + * @memberof PIXI.extras + */ +export default class AnimatedSprite extends core.Sprite +{ + /** + * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * objects that make up the animation + */ + constructor(textures) + { + super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); + + /** + * @private + */ + this._textures = null; + + /** + * @private + */ + this._durations = null; + + this.textures = textures; + + /** + * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower + * + * @member {number} + * @default 1 + */ + this.animationSpeed = 1; + + /** + * Whether or not the movie clip repeats after playing. + * + * @member {boolean} + * @default true + */ + this.loop = true; + + /** + * Function to call when a AnimatedSprite finishes playing + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onComplete = null; + + /** + * Function to call when a AnimatedSprite changes which texture is being rendered + * + * @method + * @memberof PIXI.extras.AnimatedSprite# + */ + this.onFrameChange = null; + + /** + * Elapsed time since animation has been started, used internally to display current texture + * + * @member {number} + * @private + */ + this._currentTime = 0; + + /** + * Indicates if the AnimatedSprite is currently playing + * + * @member {boolean} + * @readonly + */ + this.playing = false; + } + + /** + * Stops the AnimatedSprite + * + */ + stop() + { + if (!this.playing) + { + return; + } + + this.playing = false; + core.ticker.shared.remove(this.update, this); + } + + /** + * Plays the AnimatedSprite + * + */ + play() + { + if (this.playing) + { + return; + } + + this.playing = true; + core.ticker.shared.add(this.update, this); + } + + /** + * Stops the AnimatedSprite and goes to a specific frame + * + * @param {number} frameNumber - frame index to stop at + */ + gotoAndStop(frameNumber) + { + this.stop(); + + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Goes to a specific frame and begins playing the AnimatedSprite + * + * @param {number} frameNumber - frame index to start at + */ + gotoAndPlay(frameNumber) + { + const previousFrame = this.currentFrame; + + this._currentTime = frameNumber; + + if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + + this.play(); + } + + /** + * Updates the object transform for rendering. + * + * @private + * @param {number} deltaTime - Time since last tick. + */ + update(deltaTime) + { + const elapsed = this.animationSpeed * deltaTime; + const previousFrame = this.currentFrame; + + if (this._durations !== null) + { + let lag = this._currentTime % 1 * this._durations[this.currentFrame]; + + lag += elapsed / 60 * 1000; + + while (lag < 0) + { + this._currentTime--; + lag += this._durations[this.currentFrame]; + } + + const sign = Math.sign(this.animationSpeed * deltaTime); + + this._currentTime = Math.floor(this._currentTime); + + while (lag >= this._durations[this.currentFrame]) + { + lag -= this._durations[this.currentFrame] * sign; + this._currentTime += sign; + } + + this._currentTime += lag / this._durations[this.currentFrame]; + } + else + { + this._currentTime += elapsed; + } + + if (this._currentTime < 0 && !this.loop) + { + this.gotoAndStop(0); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (this._currentTime >= this._textures.length && !this.loop) + { + this.gotoAndStop(this._textures.length - 1); + + if (this.onComplete) + { + this.onComplete(); + } + } + else if (previousFrame !== this.currentFrame) + { + this.updateTexture(); + } + } + + /** + * Updates the displayed texture to match the current frame index + * + * @private + */ + updateTexture() + { + this._texture = this._textures[this.currentFrame]; + this._textureID = -1; + + if (this.onFrameChange) + { + this.onFrameChange(this.currentFrame); + } + } + + /** + * Stops the AnimatedSprite and destroys it + * + */ + destroy() + { + this.stop(); + super.destroy(); + } + + /** + * A short hand way of creating a movieclip from an array of frame ids + * + * @static + * @param {string[]} frames - The array of frames ids the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified frames. + */ + static fromFrames(frames) + { + const textures = []; + + for (let i = 0; i < frames.length; ++i) + { + textures.push(core.Texture.fromFrame(frames[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * A short hand way of creating a movieclip from an array of image ids + * + * @static + * @param {string[]} images - the array of image urls the movieclip will use as its texture frames + * @return {AnimatedSprite} The new movie clip with the specified images as frames. + */ + static fromImages(images) + { + const textures = []; + + for (let i = 0; i < images.length; ++i) + { + textures.push(core.Texture.fromImage(images[i])); + } + + return new AnimatedSprite(textures); + } + + /** + * totalFrames is the total number of frames in the AnimatedSprite. This is the same as number of textures + * assigned to the AnimatedSprite. + * + * @readonly + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @default 0 + */ + get totalFrames() + { + return this._textures.length; + } + + /** + * The array of textures used for this AnimatedSprite + * + * @member {PIXI.Texture[]} + * @memberof PIXI.extras.AnimatedSprite# + */ + get textures() + { + return this._textures; + } + + /** + * Sets the textures. + * + * @param {PIXI.Texture[]} value - The texture to set. + */ + set textures(value) + { + if (value[0] instanceof core.Texture) + { + this._textures = value; + this._durations = null; + } + else + { + this._textures = []; + this._durations = []; + + for (let i = 0; i < value.length; i++) + { + this._textures.push(value[i].texture); + this._durations.push(value[i].time); + } + } + } + + /** + * The AnimatedSprites current frame index + * + * @member {number} + * @memberof PIXI.extras.AnimatedSprite# + * @readonly + */ + get currentFrame() + { + let currentFrame = Math.floor(this._currentTime) % this._textures.length; + + if (currentFrame < 0) + { + currentFrame += this._textures.length; + } + + return currentFrame; + } +} diff --git a/src/extras/MovieClip.js b/src/extras/MovieClip.js deleted file mode 100644 index 5dc83e9..0000000 --- a/src/extras/MovieClip.js +++ /dev/null @@ -1,365 +0,0 @@ -import * as core from '../core'; - -/** - * @typedef FrameObject - * @type {object} - * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame - * @property {number} time - the duration of the frame in ms - */ - -/** - * A MovieClip is a simple way to display an animation depicted by a list of textures. - * - * ```js - * let alienImages = ["image_sequence_01.png","image_sequence_02.png","image_sequence_03.png","image_sequence_04.png"]; - * let textureArray = []; - * - * for (let i=0; i < 4; i++) - * { - * let texture = PIXI.Texture.fromImage(alienImages[i]); - * textureArray.push(texture); - * }; - * - * let mc = new PIXI.MovieClip(textureArray); - * ``` - * - * @class - * @extends PIXI.Sprite - * @memberof PIXI.extras - */ -export default class MovieClip extends core.Sprite -{ - /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame - * objects that make up the animation - */ - constructor(textures) - { - super(textures[0] instanceof core.Texture ? textures[0] : textures[0].texture); - - /** - * @private - */ - this._textures = null; - - /** - * @private - */ - this._durations = null; - - this.textures = textures; - - /** - * The speed that the MovieClip will play at. Higher is faster, lower is slower - * - * @member {number} - * @default 1 - */ - this.animationSpeed = 1; - - /** - * Whether or not the movie clip repeats after playing. - * - * @member {boolean} - * @default true - */ - this.loop = true; - - /** - * Function to call when a MovieClip finishes playing - * - * @method - * @memberof PIXI.extras.MovieClip# - */ - this.onComplete = null; - - /** - * Function to call when a MovieClip changes which texture is being rendered - * - * @method - * @memberof PIXI.extras.MovieClip# - */ - this.onFrameChange = null; - - /** - * Elapsed time since animation has been started, used internally to display current texture - * - * @member {number} - * @private - */ - this._currentTime = 0; - - /** - * Indicates if the MovieClip is currently playing - * - * @member {boolean} - * @readonly - */ - this.playing = false; - } - - /** - * Stops the MovieClip - * - */ - stop() - { - if (!this.playing) - { - return; - } - - this.playing = false; - core.ticker.shared.remove(this.update, this); - } - - /** - * Plays the MovieClip - * - */ - play() - { - if (this.playing) - { - return; - } - - this.playing = true; - core.ticker.shared.add(this.update, this); - } - - /** - * Stops the MovieClip and goes to a specific frame - * - * @param {number} frameNumber - frame index to stop at - */ - gotoAndStop(frameNumber) - { - this.stop(); - - const previousFrame = this.currentFrame; - - this._currentTime = frameNumber; - - if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - } - - /** - * Goes to a specific frame and begins playing the MovieClip - * - * @param {number} frameNumber - frame index to start at - */ - gotoAndPlay(frameNumber) - { - const previousFrame = this.currentFrame; - - this._currentTime = frameNumber; - - if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - - this.play(); - } - - /** - * Updates the object transform for rendering. - * - * @private - * @param {number} deltaTime - Time since last tick. - */ - update(deltaTime) - { - const elapsed = this.animationSpeed * deltaTime; - const previousFrame = this.currentFrame; - - if (this._durations !== null) - { - let lag = this._currentTime % 1 * this._durations[this.currentFrame]; - - lag += elapsed / 60 * 1000; - - while (lag < 0) - { - this._currentTime--; - lag += this._durations[this.currentFrame]; - } - - const sign = Math.sign(this.animationSpeed * deltaTime); - - this._currentTime = Math.floor(this._currentTime); - - while (lag >= this._durations[this.currentFrame]) - { - lag -= this._durations[this.currentFrame] * sign; - this._currentTime += sign; - } - - this._currentTime += lag / this._durations[this.currentFrame]; - } - else - { - this._currentTime += elapsed; - } - - if (this._currentTime < 0 && !this.loop) - { - this.gotoAndStop(0); - - if (this.onComplete) - { - this.onComplete(); - } - } - else if (this._currentTime >= this._textures.length && !this.loop) - { - this.gotoAndStop(this._textures.length - 1); - - if (this.onComplete) - { - this.onComplete(); - } - } - else if (previousFrame !== this.currentFrame) - { - this.updateTexture(); - } - } - - /** - * Updates the displayed texture to match the current frame index - * - * @private - */ - updateTexture() - { - this._texture = this._textures[this.currentFrame]; - this._textureID = -1; - - if (this.onFrameChange) - { - this.onFrameChange(this.currentFrame); - } - } - - /** - * Stops the MovieClip and destroys it - * - */ - destroy() - { - this.stop(); - super.destroy(); - } - - /** - * A short hand way of creating a movieclip from an array of frame ids - * - * @static - * @param {string[]} frames - The array of frames ids the movieclip will use as its texture frames - * @return {MovieClip} The new movie clip with the specified frames. - */ - static fromFrames(frames) - { - const textures = []; - - for (let i = 0; i < frames.length; ++i) - { - textures.push(core.Texture.fromFrame(frames[i])); - } - - return new MovieClip(textures); - } - - /** - * A short hand way of creating a movieclip from an array of image ids - * - * @static - * @param {string[]} images - the array of image urls the movieclip will use as its texture frames - * @return {MovieClip} The new movie clip with the specified images as frames. - */ - static fromImages(images) - { - const textures = []; - - for (let i = 0; i < images.length; ++i) - { - textures.push(core.Texture.fromImage(images[i])); - } - - return new MovieClip(textures); - } - - /** - * totalFrames is the total number of frames in the MovieClip. This is the same as number of textures - * assigned to the MovieClip. - * - * @readonly - * @member {number} - * @memberof PIXI.extras.MovieClip# - * @default 0 - */ - get totalFrames() - { - return this._textures.length; - } - - /** - * The array of textures used for this MovieClip - * - * @member {PIXI.Texture[]} - * @memberof PIXI.extras.MovieClip# - */ - get textures() - { - return this._textures; - } - - /** - * Sets the textures. - * - * @param {PIXI.Texture[]} value - The texture to set. - */ - set textures(value) - { - if (value[0] instanceof core.Texture) - { - this._textures = value; - this._durations = null; - } - else - { - this._textures = []; - this._durations = []; - - for (let i = 0; i < value.length; i++) - { - this._textures.push(value[i].texture); - this._durations.push(value[i].time); - } - } - } - - /** - * The MovieClips current frame index - * - * @member {number} - * @memberof PIXI.extras.MovieClip# - * @readonly - */ - get currentFrame() - { - let currentFrame = Math.floor(this._currentTime) % this._textures.length; - - if (currentFrame < 0) - { - currentFrame += this._textures.length; - } - - return currentFrame; - } -} diff --git a/src/extras/index.js b/src/extras/index.js index 7fe38b3..d8a838d 100644 --- a/src/extras/index.js +++ b/src/extras/index.js @@ -2,7 +2,7 @@ * @namespace PIXI.extras */ export { default as TextureTransform } from './TextureTransform'; -export { default as MovieClip } from './MovieClip'; +export { default as AnimatedSprite } from './AnimatedSprite'; export { default as TilingSprite } from './TilingSprite'; export { default as TilingSpriteRenderer } from './webgl/TilingSpriteRenderer'; export { default as BitmapText } from './BitmapText';