1 /**
  2  * The Render Engine
  3  * Tile
  4  *
  5  * @fileoverview A single tile, similar to a sprite but with a solidity map for collision.
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  * @author: $Author: bfattori $
  9  * @version: $Revision: 1556 $
 10  *
 11  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 12  *
 13  * Permission is hereby granted, free of charge, to any person obtaining a copy
 14  * of this software and associated documentation files (the "Software"), to deal
 15  * in the Software without restriction, including without limitation the rights
 16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 17  * copies of the Software, and to permit persons to whom the Software is
 18  * furnished to do so, subject to the following conditions:
 19  *
 20  * The above copyright notice and this permission notice shall be included in
 21  * all copies or substantial portions of the Software.
 22  *
 23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 29  * THE SOFTWARE.
 30  *
 31  */
 32 
 33 // The class this file defines and its required classes
 34 R.Engine.define({
 35     "class":"R.resources.types.Tile",
 36     "requires":[
 37         "R.resources.types.Sprite",
 38         "R.math.Rectangle2D",
 39         "R.util.RenderUtil"
 40     ]
 41 });
 42 
 43 /**
 44  * @class Represents a 2d tile.  The difference between a sprite and a tile is that
 45  *    tiles contain a "solidity map" which allows for raycasting when testing for collisions.
 46  *    Otherwise, tiles and sprites are identical.
 47  *
 48  * @constructor
 49  * @param name {String} The name of the tile within the resource
 50  * @param tileObj {Object} Passed in by a {@link R.resources.loaders.TileLoader}.  An array which defines the
 51  *    tile frame, and parameters.
 52  * @param tileResource {Object} The tile resource loaded by the {@link R.resources.loaders.TileLoader}
 53  * @description A tile is a sprite with the addition of a solidity map, computed from the
 54  *     pixels of the sprite.
 55  * @extends R.resources.types.Sprite
 56  */
 57 R.resources.types.Tile = function () {
 58     return R.resources.types.Sprite.extend(/** @scope R.resources.types.Tile.prototype */{
 59 
 60         solidityMap:null,
 61         status:null,
 62         sparsity:null,
 63         tileObj:null,
 64         renderContext:null,
 65         renderedFlag:false,
 66 
 67         /** @private */
 68         constructor:function (name, tileObj, tileResource, tileLoader) {
 69             this.base(name, tileObj, tileResource, 2, tileLoader);
 70             this.tileObj = tileObj;
 71             this.solidityMap = null;
 72             this.renderedFlag = false;
 73 
 74             if (tileResource.info.assumeOpaque) {
 75                 // Short-circuit
 76                 this.solidityMap = {
 77                     map:null,
 78                     status:R.resources.types.Tile.ALL_OPAQUE
 79                 };
 80             } else {
 81                 this.solidityMap = R.resources.types.TileMap.computeSolidityMap(this);
 82             }
 83         },
 84 
 85         /**
 86          * Destroy the sprite instance
 87          */
 88         destroy:function () {
 89             this.base();
 90         },
 91 
 92         /**
 93          * Release the sprite back into the pool for reuse
 94          */
 95         release:function () {
 96             this.solidityMap = null;
 97             this.tileObj = null;
 98             this.renderedFlag = false;
 99             this.base();
100         },
101 
102         /**
103          * Set the render context the tile is being rendered onto.  This allows tiles to
104          * be rendered properly on HTML contexts.
105          * @param renderContext {R.rendercontexts.AbstractRenderContext} The render context
106          */
107         setRenderContext:function (renderContext) {
108             if (this.renderContext == null) {
109                 this.renderContext = renderContext;
110                 if (renderContext instanceof R.rendercontexts.HTMLElementContext) {
111                     // Add the tile to the context
112                     renderContext.add(this);
113                 }
114             }
115         },
116 
117         /**
118          * Get the resource this sprite originated from
119          * @return {Object}
120          */
121         getTileResource:function () {
122             return this.resource;
123         },
124 
125         /**
126          * Get the sprite loader this sprite originated from
127          * @return {R.resources.loaders.SpriteLoader}
128          */
129         getTileLoader:function () {
130             return this.loader;
131         },
132 
133         /**
134          * Set the solidity map for the tile, used during raycasts.  The status
135          * flag is used to indicate if the pixels of the map need to be tested.
136          * A solidity map will be computed for each frame of the tile, if the tile
137          * is animated.
138          *
139          * @param frame {Number} The frame number
140          * @param solidityMap {Array} An array of bits which indicate if a pixel is opaque or transparent
141          * @param statusFlag {Number} Flag used to assist in short-circuit testing
142          */
143         setSolidityMap:function (frame, solidityMap, statusFlag) {
144             this.solidityMap = {
145                 map:solidityMap,
146                 status:statusFlag
147             };
148         },
149 
150         /**
151          * Test if the given point, local to the tile's coordinates, would
152          * result in a collision.
153          * @param point {R.math.Point2D}
154          * @param time {Number} The current world time
155          * @param dt {Number} The delta between the world time and the last time the world was updated
156          *          in milliseconds.
157          */
158         testPoint:function (point, time, dt) {
159             var sMap = this.solidityMap;
160             if (sMap.status == R.resources.types.Tile.ALL_OPAQUE) {
161                 return true;
162             } else if (sMap.status == R.resources.types.Tile.ALL_TRANSPARENT) {
163                 return false;
164             } else {
165                 return !!sMap.map[point.x + (point.y * this.getBoundingBox().w)];
166             }
167         },
168 
169         getRotation:function () {
170             return 0;
171         },
172 
173         getScale:function () {
174             return R.resources.types.Tile.SCALE1;
175         },
176 
177         /**
178          * Mark the tile as having been rendered to the context.  This is used for
179          * HTML contexts where the tile should only render once unless it's an animated tile.
180          */
181         markRendered:function () {
182             this.renderedFlag = true;
183         },
184 
185         /**
186          * Returns a flag indicating if the tile has been rendered to the context.
187          * @return {Boolean}
188          */
189         hasRendered:function () {
190             return this.renderedFlag;
191         }
192 
193     }, /** @scope R.resources.types.Tile.prototype */{
194         /**
195          * Gets the class name of this object.
196          * @return {String} The string "R.resources.types.Tile"
197          */
198         getClassName:function () {
199             return "R.resources.types.Tile";
200         },
201 
202         SCALE1:R.math.Vector2D.create(1, 1),
203 
204         /**
205          * Specialized method to allow tiles to be cloned from one another.  This method is also
206          * called by {@link R#clone} when cloning objects.
207          *
208          * @param tile {R.resources.types.Tile} Tile to clone from
209          */
210         clone:function (tile) {
211             return R.resources.types.Tile.create(tile.getName(), tile.tileObj, tile.getTileResource(), tile.getTileLoader());
212         },
213 
214         /**
215          * All pixels are mixed, either transparent or opaque.  Must perform
216          * full ray testing on the solidity map.
217          * @type {Number}
218          */
219         ALL_MIXED:0,
220 
221         /**
222          * All pixels are transparent to collisions.  Short-circuit test for ray casting.
223          * @type {Number}
224          */
225         ALL_TRANSPARENT:1,
226 
227         /**
228          * All pixels are opaque to collisions.  Short-circuit test for ray casting.
229          * @type {Number}
230          */
231         ALL_OPAQUE:2
232     });
233 
234 };
235