1 /**
  2  * The Render Engine
  3  * TileLoader
  4  *
  5  * @fileoverview An extension of the sprite resource loader for handling
  6  *               tiles.
  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.TileLoader",
 37     "requires":[
 38         "R.resources.loaders.SpriteLoader",
 39         "R.resources.types.Tile"
 40     ]
 41 });
 42 
 43 /**
 44  * @class Loads tile resources and makes them available to the system.  Tiles are
 45  *        defined by an external JSON resource file.  A tile definition file
 46  *        is a JSON file which is nearly identical to sprite sheets.  The format
 47  *        describes the image which contains the sprites, the dimensions of the image,
 48  *        the version of the file, and the tile definitions.  Tiles 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 tile and the
 54  *        width and height of the frame.  For an animation, the first four entries 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  *        <p/>
 63  *        The sparsity value is used to produce each tile's solidity map so that the map
 64  *        will consist of averaged pixels, resulting in a simplified map for collisions.
 65  *        The transparencyThreshold determines above what alpha value a pixel is no longer
 66  *        considered transparent, but solid.  Setting the assumeOpaque flag will short-circuit
 67  *        all solidity map calculations and assume all tiles to be completely opaque.
 68  *
 69  * <pre>
 70  * {
 71  *    // Tile definition file v2
 72  *    "bitmapImage": "bitmapFile.ext",
 73  *    "bitmapSize": [320, 320],
 74  *    "version": 2
 75  *    "sparsity": 1,
 76  *    "transparencyThreshold": 0,
 77  *    "assumeOpaque": false,
 78  *    "tiles": {
 79  *        "girder": [0, 0, 32, 32],
 80  *        "gears": [32, 0, 32, 32, 3, 150, "loop"]
 81  *    }
 82  * }
 83  * </pre>
 84  *        <i>Note:</i> The new file structure is a bit more compact, and is indicated with
 85  *        the "version" key in the file, set to the value 2.  Version 1 will be deprecated
 86  *        and will not be supported in a future release of The Render Engine.
 87  *
 88  * @constructor
 89  * @param name {String=TileLoader} The name of the resource loader
 90  * @extends R.resources.loaders.SpriteLoader
 91  */
 92 R.resources.loaders.TileLoader = function () {
 93     return R.resources.loaders.SpriteLoader.extend(/** @scope R.resources.loaders.TileLoader.prototype */{
 94 
 95         tiles:null,
 96 
 97         /** @private */
 98         constructor:function (name) {
 99             this.base(name || "TileLoader");
100             this.tiles = {};
101         },
102 
103         /**
104          * Called after the data has been loaded, passing along the info object and name
105          * of the sprite resource.
106          * @param name {String} The name of the sprite resource
107          * @param info {Object} The sprite resource definition
108          */
109         afterLoad:function (name, info) {
110             this.base(name, info);
111         },
112 
113         /**
114          * Creates a {@link R.resources.types.Tile} object representing the named tile.
115          *
116          * @param resource {String} The name of a loaded tile resource
117          * @param tile {String} The name of the tile from the resource
118          * @return {R.resources.types.Tile} A {@link R.resources.types.Tile} instance
119          */
120         getTile:function (resource, tile) {
121             var info = this.get(resource).info;
122             if (info != null && info.sprites[tile]) {
123                 var aTile = this.tiles[tile];
124                 if (!aTile) {
125                     // We want to make sure we only create a tile singleton, not instances for each tile
126                     aTile = this.tiles[tile] = R.resources.types.Tile.create(tile, info.sprites[tile], this.get(resource), this);
127                 }
128                 return aTile;
129             } else {
130                 return null;
131             }
132         },
133 
134         /**
135          * Export all of the tiles in the specified resource, as a JavaScript object, with the
136          * tile name as the key and the corresponding {@link R.resources.types.Tile} as the value.
137          * @param resource {String} The name of the tile resource
138          * @param [tileNames] {Array} An optional array of tiles to export, by name,
139          *         or <code>null</tt> to export all tiles
140          */
141         exportAll:function (resource, tileNames) {
142             var o = {};
143             var tiles = this.getSpriteNames(resource);
144             for (var i in tiles) {
145                 if (!tileNames || R.engine.Support.indexOf(tileNames, tiles[i]) != -1) {
146                     o[tiles[i]] = this.getTile(resource, tiles[i]);
147                 }
148             }
149             return o;
150         },
151 
152         /**
153          * Sparsity is used to reduce the size of the solidity map for each frame of every tile.
154          * The higher the sparsity, the more pixels will be averaged together to get a smaller map.
155          * This has the potential to improve performance when performing ray casting by eliminating
156          * the need to calculate collisions per pixel.
157          * @param resource {String} The name of the tile resource
158          * @return {Number}
159          */
160         getSparsity:function (resource) {
161             return this.get(resource).info.sparsity;
162         },
163 
164         /**
165          * Get the transparency threshold at which pixels are considered to be either transparent or
166          * solid.  Pixel alpha values above the specified threshold will be considered solid when
167          * calculating the solidity map of a tile.
168          * @param resource {String} The name of the tile resource
169          * @return {Number} Value between 0 and 255
170          */
171         getThreshold:function (resource) {
172             return this.get(resource).info.transparencyThreshold;
173         },
174 
175         /**
176          * Get the state of the flag indicating if all tiles should be considered fully opaque.
177          * @param resource {String} The name of the tile resource
178          * @return {Boolean}
179          */
180         getOpacityFlag:function (resource) {
181             return this.get(resource).info.assumeOpaque;
182         },
183 
184         /**
185          * The name of the resource this loader will get.
186          * @returns {String} The string "tile"
187          */
188         getResourceType:function () {
189             return "tile";
190         }
191 
192     }, /** @scope R.resources.loaders.TileLoader.prototype */ {
193         /**
194          * Get the class name of this object.
195          * @return {String} The string "R.resources.loaders.TileLoader"
196          */
197         getClassName:function () {
198             return "R.resources.loaders.TileLoader";
199         }
200     });
201 
202 }