1 /** 2 * The Render Engine 3 * SpriteLoader 4 * 5 * @fileoverview An extension of the image resource loader for handling 6 * sprites. 7 * 8 * @author: Brett Fattori (brettf@renderengine.com) 9 * @author: $Author: bfattori $ 10 * @version: $Revision: 1556 $ 11 * 12 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this software and associated documentation files (the "Software"), to deal 16 * in the Software without restriction, including without limitation the rights 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 * copies of the Software, and to permit persons to whom the Software is 19 * furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 * THE SOFTWARE. 31 * 32 */ 33 34 // The class this file defines and its required classes 35 R.Engine.define({ 36 "class":"R.resources.loaders.SpriteLoader", 37 "requires":[ 38 "R.resources.loaders.ImageLoader", 39 "R.resources.types.Sprite" 40 ] 41 }); 42 43 /** 44 * @class Loads sprite resources and makes them available to the system. Sprites are 45 * defined by an external JSON resource file. A sprite definition file 46 * is a JSON file which can support single-line comments. The format 47 * describes the image which contains the bitmap, the size of the bitmap, 48 * the version of the file, and the sprites. Sprites can be either single 49 * frames or animations. Animations are expected to be sequentially organized 50 * in the bitmap from left to right. Each frame of an animation must be the exact 51 * same dimensions. 52 * <p/> 53 * A frame is simply defined by the upper left corner of the sprite and the 54 * width and height of the frame. For an animation, the first four arguments are 55 * the same as a frame, followed by the frame count, the millisecond delay between 56 * frames, and the type of animation (either "loop" or "toggle"). A looped animation 57 * will play all frames, indicated by the frame count, and then start again from the 58 * beginning of the animation. A toggled animation will play from the first to 59 * the last frame, then play from the last to the first, and then repeat. The 60 * first and last frame will not be repeated in a toggled animation. Thus, if 61 * the frames are A, B, C, then the toggle will play as A, B, C, B, A, B... 62 * <pre> 63 * { 64 * // Sprite definition file v2 65 * "bitmapImage": "bitmapFile.ext", 66 * "bitmapSize": [320, 320], 67 * "version": 2 68 * "sprites": { 69 * "stand": [0, 0, 32, 32], 70 * "walk": [32, 0, 32, 32, 3, 150, "loop"] 71 * } 72 * } 73 * </pre> 74 * <i>Note:</i> The new file structure is a bit more compact, and is indicated with 75 * the "version" key in the file, set to the value 2. Version 1 will be deprecated 76 * and will not be supported in a future release of The Render Engine. 77 * 78 * @constructor 79 * @param name {String=SpriteLoader} The name of the resource loader 80 * @extends R.resources.loaders.ImageLoader 81 */ 82 R.resources.loaders.SpriteLoader = function () { 83 return R.resources.loaders.ImageLoader.extend(/** @scope R.resources.loaders.SpriteLoader.prototype */{ 84 85 sprites:null, 86 87 queuedSprites:0, 88 89 /** @private */ 90 constructor:function (name) { 91 this.base(name || "SpriteLoader"); 92 this.sprites = {}; 93 this.queuedSprites = 0; 94 }, 95 96 /** 97 * Load a sprite resource from a URL. 98 * 99 * @param name {String} The name of the resource 100 * @param url {String} The URL where the resource is located 101 */ 102 load:function (name, url /*, info, path */) { 103 if (!arguments[2]) { 104 var loc = window.location; 105 if (url.indexOf(loc.protocol) != -1 && url.indexOf(loc.hostname) == -1) { 106 Assert(false, "Sprites must be located on this server"); 107 } 108 109 this.queuedSprites++; 110 var thisObj = this; 111 112 // Get the file from the server 113 R.engine.Script.loadJSON(url, function (spriteInfo) { 114 // get the path to the resource file 115 var path = url.substring(0, url.lastIndexOf("/")); 116 thisObj.load(name, url, spriteInfo, path + "/"); 117 thisObj.afterLoad(name, spriteInfo, path + "/"); 118 }); 119 } 120 else { 121 var info = arguments[2], path = arguments[3]; 122 info.bitmapImage = path + info.bitmapImage; 123 R.debug.Console.info("Loading sprite: " + name + " @ " + info.bitmapImage); 124 125 // Load the sprite image file 126 if (!info.version || info.version == 1) { 127 this.base(name, info.bitmapImage, info.bitmapWidth, info.bitmapHeight); 128 } else if (info.version == 2) { 129 this.base(name, info.bitmapImage, info.bitmapSize[0], info.bitmapSize[1]); 130 } 131 132 // Store the sprite info 133 this.sprites[name] = info; 134 135 // Since the path that is stored by ImageLoader is the path to the image 136 // and not the descriptor, we need to override the value 137 this.setPathUrl(name, url); 138 139 this.queuedSprites--; 140 } 141 }, 142 143 /** 144 * Called after the data has been loaded, passing along the info object and name 145 * of the sprite resource. 146 * @param name {String} The name of the sprite resource 147 * @param info {Object} The sprite resource definition 148 */ 149 afterLoad:function (name, info) { 150 }, 151 152 /** 153 * Get the sprite resource with the specified name from the cache. The 154 * object returned contains the bitmap as <tt>image</tt> and 155 * the sprite definition as <tt>info</tt>. 156 * 157 * @param name {String} The name of the object to retrieve 158 * @return {Object} An object with two keys: "image" and "info" 159 */ 160 get:function (name) { 161 var bitmap = this.base(name); 162 var sprite = { 163 resourceName:name, 164 image:bitmap, 165 info:this.sprites[name] 166 }; 167 return sprite; 168 }, 169 170 /** 171 * Check to see if a named resource is "ready for use". 172 * @param name {String} The name of the resource to check ready status for, 173 * or <tt>null</tt> for all resources in loader. 174 * @return {Boolean} <tt>true</tt> if the resource is loaded and ready to use 175 */ 176 isReady:function (name) { 177 // If sprites are queued, we can't be totally ready 178 if (this.queuedSprites > 0) { 179 return false; 180 } 181 182 return this.base(name); 183 }, 184 185 /** 186 * Creates a {@link R.resources.types.Sprite} object representing the named sprite. 187 * 188 * @param resource {String} The name of a loaded sprite resource 189 * @param sprite {String} The name of the sprite from the resource 190 * @return {R.resources.types.Sprite} A {@link R.resources.types.Sprite} instance 191 */ 192 getSprite:function (resource, sprite) { 193 var info = this.get(resource).info; 194 return R.resources.types.Sprite.create(sprite, info.sprites[sprite], this.get(resource), info.version || 1, this); 195 }, 196 197 /** 198 * Get the names of all the sprites available in a resource. 199 * 200 * @param resource {String} The name of the resource 201 * @return {Array} All of the sprite names in the given loaded resource 202 */ 203 getSpriteNames:function (resource) { 204 var s = []; 205 var spr = this.sprites[resource].sprites; 206 for (var i in spr) { 207 s.push(i); 208 } 209 return s; 210 }, 211 212 /** 213 * Export all of the sprites in the specified resource, as a JavaScript object, with the 214 * sprite name as the key and the corresponding {@link R.resources.types.Sprite} as the value. 215 * @param resource {String} The name of the sprite resource 216 * @param [spriteNames] {Array} An optional array of sprites to export, by name, 217 * or <code>null</tt> to export all sprites 218 */ 219 exportAll:function (resource, spriteNames) { 220 var o = {}; 221 var sprites = this.getSpriteNames(resource); 222 for (var i in sprites) { 223 if (!spriteNames || R.engine.Support.indexOf(spriteNames, sprites[i]) != -1) { 224 o[sprites[i]] = this.getSprite(resource, sprites[i]); 225 } 226 } 227 return o; 228 }, 229 230 /** 231 * The name of the resource this loader will get. 232 * @returns {String} The string "sprite" 233 */ 234 getResourceType:function () { 235 return "sprite"; 236 } 237 238 }, /** @scope R.resources.loaders.SpriteLoader.prototype */ { 239 /** 240 * Get the class name of this object. 241 * @return {String} The string "R.resources.loaders.SpriteLoader" 242 */ 243 getClassName:function () { 244 return "R.resources.loaders.SpriteLoader"; 245 } 246 }); 247 248 }