API Docs for: v0.1.0
Show:

File: src\display\Sprite.js

var EventEmitter = require('../utils/EventEmitter'),
    Rectangle = require('../geom/Rectangle'),
    PhysicsTarget = require('../physics/PhysicsTarget'),
    inherit = require('../utils/inherit'),
    Texture = require('./Texture'),
    math = require('../math/math'),
    utils = require('../utils/utils'),
    PIXI = require('../vendor/pixi');

/**
 * The base Sprite class. This class is the base for all images on the screen. This class extends PIXI's Sprite.
 *
 * @class Sprite
 * @extends [PIXI.Sprite](http://www.goodboydigital.com/pixijs/docs/classes/Sprite.html)
 * @uses EventEmitter
 * @constructor
 * @param textures {Texture|Array<Texture>|Object} The texture for the sprite to display, an array of texture to animation through, or an animation object.
 *      The later looks like: `{ animationName: { frames: [frame1, frame2], speed: 0.5, loop: false } }` where each frame is a Texture object
 * @param [speed] {Number} The speed of the animations (can be overriden on a specific animations)
 * @param [start] {String} The animation to start with, defaults to the first found key otherwise
 * @example
 *      var spr = new gf.Sprite(texture);
 */
var Sprite = function(anims, speed, start) {
    EventEmitter.call(this);
    PhysicsTarget.call(this);

    if(!anims) {
        anims = Texture.__default;
    }

    //parse tx into correct format
    if(anims instanceof Texture) {
        anims = { _default: { frames: [anims] } };
        start = '_default';
    }
    else if(anims instanceof Array) {
        anims = { _default: { frames: anims } };
        start = '_default';
    } else {
        //massage animations into full format
        for(var a in anims) {
            if(start === undefined)
                start = a;

            var anim = anims[a];

            if(anim instanceof Array)
                anims[a] = { name: a, frames: anim };
            else if(anim instanceof Texture)
                anims[a] = { name: a, frames: [anim] };
            else
                anims[a].name = a;
        }
    }

    PIXI.Sprite.call(this, anims[start].frames[0]);

    /**
     * The name of the sprite
     *
     * @property name
     * @type String
     * @default ''
     */
    this.name = '';

    /**
     * The lifetime of the sprite. Once it reaches 0 (after being set)
     * the sprite's visible property is set to false, so that it will
     * no longer be rendered. NOT YET IMPLEMENTED
     *
     * @property lifetime
     * @type Number
     * @default Infinity
     * @private
     */
    this.lifespan = Infinity;

    /**
     * The animation speed for this sprite
     *
     * @property speed
     * @type Number
     * @default 1
     */
    this.speed = speed || 1;

    /**
     * Whether or not to loop the animations. This can be overriden
     * on a per-animation level
     *
     * @property loop
     * @type Boolean
     * @default false
     */
    this.loop = false;

    /**
     * The registerd animations for this AnimatedSprite
     *
     * @property animations
     * @type Object
     * @readOnly
     */
    this.animations = anims;

    /**
     * The currently playing animation
     *
     * @property currentAnimation
     * @type String
     * @readOnly
     */
    this.currentAnimation = start;

    /**
     * The current frame being shown
     *
     * @property currentFrame
     * @type Number
     * @readOnly
     */
    this.currentFrame = 0;

    /**
     * Whether or not the animation is currently playing
     *
     * @property playing
     * @type Boolean
     * @readOnly
     */
    this.playing = false;

    this.hitArea = this.hitArea || new Rectangle(0, 0, this.width, this.height);

    //show first frame
    this.goto(0, this.currentAnimation);

    /**
     * Fired when a new frame of the running animation is shown
     *
     * @event frame
     * @param animation {String} The animation name that is playing
     * @param frameId {Number} The frame that is being shown
     */

    /**
     * Fired when the running animation completes
     *
     * @event complete
     * @param animation {String} The animation that has completed
     */
};

inherit(Sprite, PIXI.Sprite, {
    /**
     * Sets the sprite to visible = true
     *
     * @method show
     * @return {Sprite} Returns itself.
     * @chainable
     */
    show: function() {
        this.visible = true;
        return this;
    },
    /**
     * Sets the sprite to visible = false
     *
     * @method hide
     * @return {Sprite} Returns itself.
     * @chainable
     */
    hide: function() {
        this.visible = false;
        return this;
    },
    /**
     * Creates a new Sprite instance with the same values as this one
     *
     * @method clone
     * @return {Sprite} Returns the new sprite
     */
    clone: function() {
        //make a copy of our animations object
        var anims = utils.extend(true, {}, this.animations),
            spr = new Sprite(anims, this.speed, this.currentAnimation);

        spr.name = this.name;
        spr.loop = this.loop;
        spr.currentFrame = this.currentFrame;
        spr.playing = this.playing;
        spr.hitArea = this.hitArea.clone();

        spr.body = this.body.clone();

        spr.blendMode = this.blendMode;

        spr.anchor.x = this.anchor.x;
        spr.anchor.y = this.anchor.y;

        spr.position.x = this.position.x;
        spr.position.y = this.position.y;

        spr.scale.x = this.scale.x;
        spr.scale.y = this.scale.y;

        spr.pivot.x = this.pivot.x;
        spr.pivot.y = this.pivot.y;

        spr.rotation = this.rotation;
        spr.alpha = this.alpha;
        spr.visible = this.visible;
        spr.buttonMode = this.buttonMode;
        spr.renderable = this.renderable;

        //Don't copy some pixi stuff

        //spr.children = this.children;
        //spr.parent = this.parent;
        //spr.stage = this.stage;
        //spr.worldAlpha = this.worldAlpha;
        //spr._interactive = this._interactive;
        //spr.worldTransform = this.worldTransform;
        //spr.localTransform = this.localTransform;
        //spr.color = this.color;
        //spr.dynamic = this.dynamic;

        return spr;
    },
    /**
     * Adds a new animation to this animated sprite
     *
     * @method addAnimation
     * @param name {String} The string name of the animation
     * @param frames {Array<Texture>} The array of texture frames
     * @param [speed] {Number} The animation speed
     * @param [loop] {Boolean} Loop the animation or not
     * @return {Sprite} Returns itself.
     * @chainable
     */
    addAnimation: function(name, frames, speed, loop) {
        if(typeof name === 'object') {
            this.animations[name.name] = name;
        } else {
            this.animations[name] = {
                name: name,
                frames: frames,
                speed: speed,
                loop: loop
            };
        }

        return this;
    },
    /**
     * Goes to a frame and starts playing the animation from there. You can optionally
     * pass the name of a new aniamtion to start playing.
     *
     * @method goto
     * @param frame {Number} The index of the frame to start on
     * @param [name] {String} The string name of the animation to go to
     * @return {Sprite} Returns itself.
     * @chainable
     */
    goto: function(frame, anim) {
        if(typeof frame === 'string') {
            anim = frame;
            frame = 0;
        }

        this.currentFrame = frame || 0;
        this.lastRound = math.round(frame || 0);

        if(anim) {
            this.currentAnimation = anim;
        }

        this.setTexture(this.animations[this.currentAnimation].frames[this.currentFrame]);
        this.emit('frame', this.currentAnimation, this.lastRound);

        return this;
    },
    /**
     * Starts playing the currently active animation
     *
     * @method play
     * @return {Sprite} Returns itself.
     * @chainable
     */
    play: function() {
        this.playing = true;
        return this;
    },
    /**
     * Stops playing the currently active animation
     *
     * @method stop
     * @return {Sprite} Returns itself.
     * @chainable
     */
    stop: function() {
        this.playing = false;
        return this;
    },
    /**
     * Removes this sprite from the stage and the physics system
     *
     * @method destroy
     */
    destroy: function() {
        this.stop();
        this.disablePhysics();

        if(this.parent)
            this.parent.removeChild(this);

        this.name = null;
        this.lifetime = null;
        this.speed = null;
        this.loop = null;
        this.animations = null;
        this.currentAnimation = null;
        this.currentFrame = null;
        this.playing = null;
        this.hitArea = null;
    },
    /**
     * Called by PIXI to update our textures and do the actual animation
     *
     * @method updateTransform
     * @private
     */
    updateTransform: function() {
        PIXI.Sprite.prototype.updateTransform.call(this);

        if(!this.playing) return;

        var anim = this.animations[this.currentAnimation],
            round,
            loop = anim.loop !== undefined ? anim.loop : this.loop;

        this.currentFrame += anim.speed || this.speed;
        round = math.round(this.currentFrame);

        if(round < anim.frames.length) {
            if(round !== this.lastRound) {
                this.lastRound = round;
                this.setTexture(anim.frames[round]);
                this.emit('frame', this.currentAnimation, round);
            }
        }
        else {
            if(loop) {
                this.goto(0);
            } else {
                this.stop();
                this.emit('complete', this.currentAnimation);
            }
        }
    }
});

module.exports = Sprite;

//Add event echos
/*
['click', 'mousedown', 'mouseup', 'mouseupoutside', 'mouseover', 'mouseout', 'mousemove', 'tap', 'touchstart', 'touchend', 'touchendoutside'].forEach(function(evtname) {
    Sprite.prototype[evtname] = module.exports = function(e) {
        this.emit(evtname, e);
    };
});
*/

/*
 * MOUSE Callbacks
 */

/**
 * A callback that is used when the users clicks on the sprite with their mouse
 *
 * @event click
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user clicks the mouse down over the sprite
 *
 * @event mousedown
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user releases the mouse that was over the sprite
 * for this callback to be fired the mouse must have been pressed down over the sprite
 *
 * @event mouseup
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user releases the mouse that was over the sprite but is no longer over the sprite
 * for this callback to be fired, The touch must have started over the sprite
 *
 * @event mouseupoutside
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the users mouse rolls over the sprite
 *
 * @event mouseover
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the users mouse leaves the sprite
 *
 * @event mouseout
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user moves the mouse while over the sprite
 *
 * @event mousemove
 * @param interactionData {InteractionData}
 */

/*
 * TOUCH Callbacks
 */

/**
 * A callback that is used when the users taps on the sprite with their finger
 * basically a touch version of click
 *
 * @event tap
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user touch's over the sprite
 *
 * @event touchstart
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user releases a touch over the sprite
 *
 * @event touchend
 * @param interactionData {InteractionData}
 */

/**
 * A callback that is used when the user releases the touch that was over the sprite
 * for this callback to be fired, The touch must have started over the sprite
 *
 * @event touchendoutside
 * @param interactionData {InteractionData}
 */