/* * SpriteSheet * Visit http://createjs.com/ for documentation, updates and examples. * * Copyright (c) 2010 gskinner.com, inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // namespace: this.createjs = this.createjs||{}; (function() { /** * Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually * animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100 * images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high). * * The data passed to the SpriteSheet constructor defines three critical pieces of information:
    *
  1. The image or images to use.
  2. *
  3. The positions of individual image frames. This data can be represented in one of two ways: * As a regular grid of sequential, equal-sized frames, or as individually defined, variable sized frames arranged in * an irregular (non-sequential) fashion.
  4. *
  5. Likewise, animations can be represented in two ways: As a series of sequential frames, defined by a start and * end frame [0,3], or as a list of frames [0,1,2,3].
  6. *
* *

SpriteSheet Format

* * data = { * * // DEFINING IMAGES: * // list of images or image URIs to use. SpriteSheet can handle preloading. * // the order dictates their index value for frame definition. * images: [image1, "path/to/image2.png"], * * // DEFINING FRAMES: * // the simple way to define frames, only requires frame size because frames are consecutive: * // define frame width/height, and optionally the frame count and registration point x/y. * // if count is omitted, it will be calculated automatically based on image dimensions. * frames: {width:64, height:64, count:20, regX: 32, regY:64}, * * // OR, the complex way that defines individual rects for frames. * // The 5th value is the image index per the list defined in "images" (defaults to 0). * frames: [ * // x, y, width, height, imageIndex, regX, regY * [0,0,64,64,0,32,64], * [64,0,96,64,0] * ], * * // DEFINING ANIMATIONS: * * // simple animation definitions. Define a consecutive range of frames. * // also optionally define a "next" animation name for sequencing. * // setting next to false makes it pause when it reaches the end. * animations: { * // start, end, next, frequency * run: [0,8], * jump: [9,12,"run",2], * stand: 13 * } * * // the complex approach which specifies every frame in the animation by index. * animations: { * run: { * frames: [1,2,3,3,2,1] * }, * jump: { * frames: [1,4,5,6,1], * next: "run", * frequency: 2 * }, * stand: { frames: [7] } * } * * // the above two approaches can be combined, you can also use a single frame definition: * animations: { * run: [0,8,true,2], * jump: { * frames: [8,9,10,9,8], * next: "run", * frequency: 2 * }, * stand: 7 * } * } * *

Example

* To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with two * animations, "run" looping from frame 0-4 inclusive, and "jump" playing from frame 5-8 and sequencing back to run: * * var data = { * images: ["sprites.jpg"], * frames: {width:50, height:50}, * animations: {run:[0,4], jump:[5,8,"run"]} * }; * var animation = new createjs.BitmapAnimation(data); * animation.gotoAndPlay("run"); * * @class SpriteSheet * @constructor * @param data * @uses EventDispatcher **/ var SpriteSheet = function(data) { this.initialize(data); } var p = SpriteSheet.prototype; // events: /** * Dispatched when all images are loaded. Note that this only fires if the images * were not fully loaded when the sprite sheet was initialized. You should check the complete property * to prior to adding a listener. Ex. *
var sheet = new SpriteSheet(data);
	 * if (!sheet.complete) {
	 *    // not preloaded, listen for onComplete:
	 *    sheet.addEventListener("complete", handler);
	 * }
* @event complete * @param {Object} target The object that dispatched the event. * @param {String} type The event type. * @since 0.6.0 */ // public properties: /** * Read-only property indicating whether all images are finished loading. * @property complete * @type Boolean **/ p.complete = true; /** * The onComplete callback is called when all images are loaded. Note that this only fires if the images * were not fully loaded when the sprite sheet was initialized. You should check the complete property * to prior to adding an onComplete handler. Ex. *
var sheet = new SpriteSheet(data);
	 * if (!sheet.complete) {
	 *    // not preloaded, listen for onComplete:
	 *    sheet.onComplete = handler;
	 * }
* @property onComplete * @type Function * @deprecated In favour of the "complete" event. Will be removed in a future version. **/ p.onComplete = null; // mix-ins: // EventDispatcher methods: p.addEventListener = null; p.removeEventListener = null; p.removeAllEventListeners = null; p.dispatchEvent = null; p.hasEventListener = null; p._listeners = null; createjs.EventDispatcher.initialize(p); // inject EventDispatcher methods. // private properties: /** * @property _animations * @protected **/ p._animations = null; /** * @property _frames * @protected **/ p._frames = null; /** * @property _images * @protected **/ p._images = null; /** * @property _data * @protected **/ p._data = null; /** * @property _loadCount * @protected **/ p._loadCount = 0; // only used for simple frame defs: /** * @property _frameHeight * @protected **/ p._frameHeight = 0; /** * @property _frameWidth * @protected **/ p._frameWidth = 0; /** * @property _numFrames * @protected **/ p._numFrames = 0; /** * @property _regX * @protected **/ p._regX = 0; /** * @property _regY * @protected **/ p._regY = 0; // constructor: /** * @method initialize * @protected **/ p.initialize = function(data) { var i,l,o,a; if (data == null) { return; } // parse images: if (data.images && (l=data.images.length) > 0) { a = this._images = []; for (i=0; i0 ? Math.min(this._numFrames-ttlFrames,cols*rows) : cols*rows; for (var j=0;j