1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 /** 28 * <p>cc.TMXLayer represents the TMX layer. </p> 29 * 30 * <p>It is a subclass of cc.SpriteBatchNode. By default the tiles are rendered using a cc.TextureAtlas. <br /> 31 * If you modify a tile on runtime, then, that tile will become a cc.Sprite, otherwise no cc.Sprite objects are created. <br /> 32 * The benefits of using cc.Sprite objects as tiles are: <br /> 33 * - tiles (cc.Sprite) can be rotated/scaled/moved with a nice API </p> 34 * 35 * <p>If the layer contains a property named "cc.vertexz" with an integer (in can be positive or negative), <br /> 36 * then all the tiles belonging to the layer will use that value as their OpenGL vertex Z for depth. </p> 37 * 38 * <p>On the other hand, if the "cc.vertexz" property has the "automatic" value, then the tiles will use an automatic vertex Z value. <br /> 39 * Also before drawing the tiles, GL_ALPHA_TEST will be enabled, and disabled after drawing them. The used alpha func will be: </p> 40 * 41 * glAlphaFunc( GL_GREATER, value ) <br /> 42 * 43 * <p>"value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer. <br /> 44 * The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a different value, like 0.5.</p> 45 * @class 46 * @extends cc.SpriteBatchNode 47 * 48 * @property {Array} tiles - Tiles for layer 49 * @property {cc.TMXTilesetInfo} tileset - Tileset for layer 50 * @property {Number} layerOrientation - Layer orientation 51 * @property {Array} properties - Properties from the layer. They can be added using tilemap editors 52 * @property {String} layerName - Name of the layer 53 * @property {Number} layerWidth - Width of the layer 54 * @property {Number} layerHeight - Height of the layer 55 * @property {Number} tileWidth - Width of a tile 56 * @property {Number} tileHeight - Height of a tile 57 */ 58 cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ 59 tiles: null, 60 tileset: null, 61 layerOrientation: null, 62 properties: null, 63 layerName: "", 64 65 _textures: null, 66 _texGrids: null, 67 _spriteTiles: null, 68 69 //size of the layer in tiles 70 _layerSize: null, 71 _mapTileSize: null, 72 //TMX Layer supports opacity 73 _opacity: 255, 74 _minGID: null, 75 _maxGID: null, 76 //Only used when vertexZ is used 77 _vertexZvalue: null, 78 _useAutomaticVertexZ: null, 79 //used for optimization 80 _reusedTile: null, 81 _atlasIndexArray: null, 82 //used for retina display 83 _contentScaleFactor: null, 84 85 _className:"TMXLayer", 86 87 /** 88 * Creates a cc.TMXLayer with an tile set info, a layer info and a map info <br/> 89 * Constructor of cc.TMXLayer 90 * @param {cc.TMXTilesetInfo} tilesetInfo 91 * @param {cc.TMXLayerInfo} layerInfo 92 * @param {cc.TMXMapInfo} mapInfo 93 */ 94 ctor:function (tilesetInfo, layerInfo, mapInfo) { 95 cc.SpriteBatchNode.prototype.ctor.call(this); 96 this._descendants = []; 97 98 this._layerSize = cc.size(0, 0); 99 this._mapTileSize = cc.size(0, 0); 100 this._spriteTiles = {}; 101 102 if(mapInfo !== undefined) 103 this.initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo); 104 }, 105 106 _createRenderCmd: function(){ 107 if(cc._renderType === cc.game.RENDER_TYPE_CANVAS) 108 return new cc.TMXLayer.CanvasRenderCmd(this); 109 else 110 return new cc.TMXLayer.WebGLRenderCmd(this); 111 }, 112 113 _fillTextureGrids: function (tileset, texId) { 114 var tex = this._textures[texId]; 115 if (!tex.isLoaded()) { 116 tex.addEventListener("load", function () { 117 this._fillTextureGrids(tileset, texId); 118 }, this); 119 return; 120 } 121 if (!tileset.imageSize.width || !tileset.imageSize.height) { 122 tileset.imageSize.width = tex.width; 123 tileset.imageSize.height = tex.height; 124 } 125 var tw = tileset._tileSize.width, 126 th = tileset._tileSize.height, 127 imageW = tex._contentSize.width, 128 imageH = tex._contentSize.height, 129 spacing = tileset.spacing, 130 margin = tileset.margin, 131 132 cols = Math.floor((imageW - margin*2 + spacing) / (tw + spacing)), 133 rows = Math.floor((imageH - margin*2 + spacing) / (th + spacing)), 134 count = rows * cols, 135 136 gid = tileset.firstGid, 137 maxGid = tileset.firstGid + count, 138 grids = this._texGrids, 139 grid = null, 140 override = grids[gid] ? true : false, 141 142 t, l, r, b; 143 144 for (; gid < maxGid; ++gid) { 145 // Avoid overlapping 146 if (override && !grids[gid]) { 147 override = false; 148 } 149 if (!override && grids[gid]) { 150 break; 151 } 152 153 grid = { 154 texId: texId, 155 x: 0, y: 0, width: tw, height: th, 156 t: 0, l: 0, r: 0, b: 0 157 }; 158 tileset.rectForGID(gid, grid); 159 grid.t = grid.y / imageH; 160 grid.l = grid.x / imageW; 161 grid.r = (grid.x + grid.width) / imageW; 162 grid.b = (grid.y + grid.height) / imageH; 163 grids[gid] = grid; 164 } 165 }, 166 167 /** 168 * Initializes a cc.TMXLayer with a tileset info, a layer info and a map info 169 * @param {cc.TMXTilesetInfo} tilesetInfo 170 * @param {cc.TMXLayerInfo} layerInfo 171 * @param {cc.TMXMapInfo} mapInfo 172 * @return {Boolean} 173 */ 174 initWithTilesetInfo:function (tilesetInfo, layerInfo, mapInfo) { 175 var size = layerInfo._layerSize; 176 var totalNumberOfTiles = parseInt(size.width * size.height); 177 178 // layerInfo 179 this.layerName = layerInfo.name; 180 this.tiles = layerInfo._tiles; 181 this.properties = layerInfo.properties; 182 this._layerSize = size; 183 this._minGID = layerInfo._minGID; 184 this._maxGID = layerInfo._maxGID; 185 this._opacity = layerInfo._opacity; 186 187 // tilesetInfo 188 this.tileset = tilesetInfo; 189 190 // mapInfo 191 this.layerOrientation = mapInfo.orientation; 192 this._mapTileSize = mapInfo.getTileSize(); 193 194 var tilesets = mapInfo._tilesets; 195 if (tilesets) { 196 this._textures = []; 197 this._texGrids = []; 198 var i, len = tilesets.length, tileset, tex; 199 for (i = 0; i < len; ++i) { 200 tileset = tilesets[i]; 201 tex = cc.textureCache.addImage(tileset.sourceImage); 202 this._textures.push(tex); 203 this._fillTextureGrids(tileset, i); 204 if (tileset === tilesetInfo) { 205 this._texture = tex; 206 } 207 } 208 } 209 210 // offset (after layer orientation is set); 211 var offset = this._calculateLayerOffset(layerInfo.offset); 212 this.setPosition(cc.pointPixelsToPoints(offset)); 213 214 // Parse cocos2d properties 215 this._parseInternalProperties(); 216 217 this.setContentSize(cc.sizePixelsToPoints(cc.size(this._layerSize.width * this._mapTileSize.width, 218 this._layerSize.height * this._mapTileSize.height))); 219 this._useAutomaticVertexZ = false; 220 this._vertexZvalue = 0; 221 return true; 222 }, 223 224 /** 225 * Gets layer size. 226 * @return {cc.Size} 227 */ 228 getLayerSize:function () { 229 return cc.size(this._layerSize.width, this._layerSize.height); 230 }, 231 232 /** 233 * Set layer size 234 * @param {cc.Size} Var 235 */ 236 setLayerSize:function (Var) { 237 this._layerSize.width = Var.width; 238 this._layerSize.height = Var.height; 239 }, 240 241 _getLayerWidth: function () { 242 return this._layerSize.width; 243 }, 244 _setLayerWidth: function (width) { 245 this._layerSize.width = width; 246 }, 247 _getLayerHeight: function () { 248 return this._layerSize.height; 249 }, 250 _setLayerHeight: function (height) { 251 this._layerSize.height = height; 252 }, 253 254 /** 255 * Size of the map's tile (could be different from the tile's size) 256 * @return {cc.Size} 257 */ 258 getMapTileSize:function () { 259 return cc.size(this._mapTileSize.width,this._mapTileSize.height); 260 }, 261 262 /** 263 * Set the map tile size. 264 * @param {cc.Size} Var 265 */ 266 setMapTileSize:function (Var) { 267 this._mapTileSize.width = Var.width; 268 this._mapTileSize.height = Var.height; 269 }, 270 271 _getTileWidth: function () { 272 return this._mapTileSize.width; 273 }, 274 _setTileWidth: function (width) { 275 this._mapTileSize.width = width; 276 }, 277 _getTileHeight: function () { 278 return this._mapTileSize.height; 279 }, 280 _setTileHeight: function (height) { 281 this._mapTileSize.height = height; 282 }, 283 284 /** 285 * Pointer to the map of tiles 286 * @return {Array} 287 */ 288 getTiles:function () { 289 return this.tiles; 290 }, 291 292 /** 293 * Pointer to the map of tiles 294 * @param {Array} Var 295 */ 296 setTiles:function (Var) { 297 this.tiles = Var; 298 }, 299 300 /** 301 * Tile set information for the layer 302 * @return {cc.TMXTilesetInfo} 303 */ 304 getTileset:function () { 305 return this.tileset; 306 }, 307 308 /** 309 * Tile set information for the layer 310 * @param {cc.TMXTilesetInfo} Var 311 */ 312 setTileset:function (Var) { 313 this.tileset = Var; 314 }, 315 316 /** 317 * Layer orientation, which is the same as the map orientation 318 * @return {Number} 319 */ 320 getLayerOrientation:function () { 321 return this.layerOrientation; 322 }, 323 324 /** 325 * Layer orientation, which is the same as the map orientation 326 * @param {Number} Var 327 */ 328 setLayerOrientation:function (Var) { 329 this.layerOrientation = Var; 330 }, 331 332 /** 333 * properties from the layer. They can be added using Tiled 334 * @return {Array} 335 */ 336 getProperties:function () { 337 return this.properties; 338 }, 339 340 /** 341 * properties from the layer. They can be added using Tiled 342 * @param {Array} Var 343 */ 344 setProperties:function (Var) { 345 this.properties = Var; 346 }, 347 348 /** 349 * Return the value for the specific property name 350 * @param {String} propertyName 351 * @return {*} 352 */ 353 getProperty:function (propertyName) { 354 return this.properties[propertyName]; 355 }, 356 357 /** 358 * Gets the layer name 359 * @return {String} 360 */ 361 getLayerName:function () { 362 return this.layerName; 363 }, 364 365 /** 366 * Set the layer name 367 * @param {String} layerName 368 */ 369 setLayerName:function (layerName) { 370 this.layerName = layerName; 371 }, 372 373 /** 374 * <p>Dealloc the map that contains the tile position from memory. <br /> 375 * Unless you want to know at runtime the tiles positions, you can safely call this method. <br /> 376 * If you are going to call layer.getTileGIDAt() then, don't release the map</p> 377 */ 378 releaseMap:function () { 379 this._spriteTiles = {}; 380 }, 381 382 /** 383 * <p>Returns the tile (cc.Sprite) at a given a tile coordinate. <br/> 384 * The returned cc.Sprite will be already added to the cc.TMXLayer. Don't add it again.<br/> 385 * The cc.Sprite can be treated like any other cc.Sprite: rotated, scaled, translated, opacity, color, etc. <br/> 386 * You can remove either by calling: <br/> 387 * - layer.removeChild(sprite, cleanup); <br/> 388 * - or layer.removeTileAt(ccp(x,y)); </p> 389 * @param {cc.Point|Number} pos or x 390 * @param {Number} [y] 391 * @return {cc.Sprite} 392 */ 393 getTileAt: function (pos, y) { 394 if (pos === undefined) { 395 throw new Error("cc.TMXLayer.getTileAt(): pos should be non-null"); 396 } 397 var x = pos; 398 if (y === undefined) { 399 x = pos.x; 400 y = pos.y; 401 } 402 if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) { 403 throw new Error("cc.TMXLayer.getTileAt(): invalid position"); 404 } 405 if (!this.tiles) { 406 cc.log("cc.TMXLayer.getTileAt(): TMXLayer: the tiles map has been released"); 407 return null; 408 } 409 410 var tile = null, gid = this.getTileGIDAt(x, y); 411 412 // if GID == 0, then no tile is present 413 if (gid === 0) { 414 return tile; 415 } 416 417 var z = 0 | (x + y * this._layerSize.width); 418 tile = this._spriteTiles[z]; 419 // tile not created yet. create it 420 if (!tile) { 421 var rect = this._texGrids[gid]; 422 var tex = this._textures[rect.texId]; 423 rect = cc.rectPixelsToPoints(rect); 424 425 tile = new cc.Sprite(tex, rect); 426 tile.setPosition(this.getPositionAt(x, y)); 427 var vertexZ = this._vertexZForPos(x, y); 428 tile.setVertexZ(vertexZ); 429 tile.setAnchorPoint(0, 0); 430 tile.setOpacity(this._opacity); 431 432 this.addChild(tile, vertexZ, z); 433 } 434 return tile; 435 }, 436 437 /** 438 * Returns the tile gid at a given tile coordinate. <br /> 439 * if it returns 0, it means that the tile is empty. <br /> 440 * This method requires the the tile map has not been previously released (eg. don't call layer.releaseMap())<br /> 441 * @param {cc.Point|Number} pos or x 442 * @param {Number} [y] 443 * @return {Number} 444 */ 445 getTileGIDAt:function (pos, y) { 446 if (pos === undefined) { 447 throw new Error("cc.TMXLayer.getTileGIDAt(): pos should be non-null"); 448 } 449 var x = pos; 450 if (y === undefined) { 451 x = pos.x; 452 y = pos.y; 453 } 454 if (x >= this._layerSize.width || y >= this._layerSize.height || x < 0 || y < 0) { 455 throw new Error("cc.TMXLayer.getTileGIDAt(): invalid position"); 456 } 457 if (!this.tiles) { 458 cc.log("cc.TMXLayer.getTileGIDAt(): TMXLayer: the tiles map has been released"); 459 return null; 460 } 461 462 var idx = 0 | (x + y * this._layerSize.width); 463 // Bits on the far end of the 32-bit global tile ID are used for tile flags 464 var tile = this.tiles[idx]; 465 466 return (tile & cc.TMX_TILE_FLIPPED_MASK) >>> 0; 467 }, 468 // XXX: deprecated 469 // tileGIDAt:getTileGIDAt, 470 471 /** 472 * <p>Sets the tile gid (gid = tile global id) at a given tile coordinate.<br /> 473 * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor . Tileset Mgr +1.<br /> 474 * If a tile is already placed at that position, then it will be removed.</p> 475 * @param {Number} gid 476 * @param {cc.Point|Number} posOrX position or x 477 * @param {Number} flagsOrY flags or y 478 * @param {Number} [flags] 479 */ 480 setTileGID: function(gid, posOrX, flagsOrY, flags) { 481 if (posOrX === undefined) { 482 throw new Error("cc.TMXLayer.setTileGID(): pos should be non-null"); 483 } 484 var pos; 485 if (flags !== undefined) { 486 pos = cc.p(posOrX, flagsOrY); 487 } else { 488 pos = posOrX; 489 flags = flagsOrY; 490 } 491 if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) { 492 throw new Error("cc.TMXLayer.setTileGID(): invalid position"); 493 } 494 if (!this.tiles) { 495 cc.log("cc.TMXLayer.setTileGID(): TMXLayer: the tiles map has been released"); 496 return; 497 } 498 if (gid !== 0 && gid < this.tileset.firstGid) { 499 cc.log( "cc.TMXLayer.setTileGID(): invalid gid:" + gid); 500 return; 501 } 502 503 flags = flags || 0; 504 var currentFlags = this.getTileFlagsAt(pos); 505 var currentGID = this.getTileGIDAt(pos); 506 507 if (currentGID !== gid || currentFlags !== flags) { 508 var gidAndFlags = (gid | flags) >>> 0; 509 // setting gid=0 is equal to remove the tile 510 if (gid === 0) 511 this.removeTileAt(pos); 512 else if (currentGID === 0) // empty tile. create a new one 513 this._updateTileForGID(gidAndFlags, pos); 514 else { // modifying an existing tile with a non-empty tile 515 var z = pos.x + pos.y * this._layerSize.width; 516 var sprite = this.getChildByTag(z); 517 if (sprite) { 518 var rect = this._texGrids[gid]; 519 var tex = this._textures[rect.texId]; 520 rect = cc.rectPixelsToPoints(rect); 521 sprite.setTexture(tex); 522 sprite.setTextureRect(rect, false); 523 if (flags != null) 524 this._setupTileSprite(sprite, pos, gidAndFlags); 525 526 this.tiles[z] = gidAndFlags; 527 } else { 528 this._updateTileForGID(gidAndFlags, pos); 529 } 530 } 531 } 532 }, 533 534 addChild: function (child, localZOrder, tag) { 535 cc.Node.prototype.addChild.call(this, child, localZOrder, tag); 536 if (tag !== undefined) { 537 this._spriteTiles[tag] = child; 538 child._vertexZ = this._vertexZ + cc.renderer.assignedZStep * tag / this.tiles.length; 539 // child._renderCmd._needDraw = false; 540 } 541 }, 542 543 removeChild: function (child, cleanup) { 544 if (this._spriteTiles[child.tag]) { 545 this._spriteTiles[child.tag] = null; 546 // child._renderCmd._needDraw = true; 547 } 548 cc.Node.prototype.removeChild.call(this, child, cleanup); 549 }, 550 551 /** 552 * lipped tiles can be changed dynamically 553 * @param {cc.Point|Number} pos or x 554 * @param {Number} [y] 555 * @return {Number} 556 */ 557 getTileFlagsAt:function (pos, y) { 558 if(!pos) 559 throw new Error("cc.TMXLayer.getTileFlagsAt(): pos should be non-null"); 560 if(y !== undefined) 561 pos = cc.p(pos, y); 562 if(pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) 563 throw new Error("cc.TMXLayer.getTileFlagsAt(): invalid position"); 564 if(!this.tiles){ 565 cc.log("cc.TMXLayer.getTileFlagsAt(): TMXLayer: the tiles map has been released"); 566 return null; 567 } 568 569 var idx = 0 | (pos.x + pos.y * this._layerSize.width); 570 // Bits on the far end of the 32-bit global tile ID are used for tile flags 571 var tile = this.tiles[idx]; 572 573 return (tile & cc.TMX_TILE_FLIPPED_ALL) >>> 0; 574 }, 575 // XXX: deprecated 576 // tileFlagAt:getTileFlagsAt, 577 578 /** 579 * Removes a tile at given tile coordinate 580 * @param {cc.Point|Number} pos position or x 581 * @param {Number} [y] 582 */ 583 removeTileAt:function (pos, y) { 584 if (!pos) { 585 throw new Error("cc.TMXLayer.removeTileAt(): pos should be non-null"); 586 } 587 if (y !== undefined) { 588 pos = cc.p(pos, y); 589 } 590 if (pos.x >= this._layerSize.width || pos.y >= this._layerSize.height || pos.x < 0 || pos.y < 0) { 591 throw new Error("cc.TMXLayer.removeTileAt(): invalid position"); 592 } 593 if (!this.tiles) { 594 cc.log("cc.TMXLayer.removeTileAt(): TMXLayer: the tiles map has been released"); 595 return; 596 } 597 598 var gid = this.getTileGIDAt(pos); 599 if (gid !== 0) { 600 var z = 0 | (pos.x + pos.y * this._layerSize.width); 601 // remove tile from GID map 602 this.tiles[z] = 0; 603 604 // remove it from sprites and/or texture atlas 605 var sprite = this._spriteTiles[z]; 606 if (sprite) { 607 this.removeChild(sprite, true); 608 } 609 } 610 }, 611 612 /** 613 * Returns the position in pixels of a given tile coordinate 614 * @param {cc.Point|Number} pos position or x 615 * @param {Number} [y] 616 * @return {cc.Point} 617 */ 618 getPositionAt:function (pos, y) { 619 if (y !== undefined) 620 pos = cc.p(pos, y); 621 var ret = cc.p(0,0); 622 switch (this.layerOrientation) { 623 case cc.TMX_ORIENTATION_ORTHO: 624 ret = this._positionForOrthoAt(pos); 625 break; 626 case cc.TMX_ORIENTATION_ISO: 627 ret = this._positionForIsoAt(pos); 628 break; 629 case cc.TMX_ORIENTATION_HEX: 630 ret = this._positionForHexAt(pos); 631 break; 632 } 633 return cc.pointPixelsToPoints(ret); 634 }, 635 // XXX: Deprecated. For backward compatibility only 636 // positionAt:getPositionAt, 637 638 _positionForIsoAt:function (pos) { 639 return cc.p(this._mapTileSize.width / 2 * ( this._layerSize.width + pos.x - pos.y - 1), 640 this._mapTileSize.height / 2 * (( this._layerSize.height * 2 - pos.x - pos.y) - 2)); 641 }, 642 643 _positionForOrthoAt:function (pos) { 644 return cc.p(pos.x * this._mapTileSize.width, 645 (this._layerSize.height - pos.y - 1) * this._mapTileSize.height); 646 }, 647 648 _positionForHexAt:function (pos) { 649 var diffY = (pos.x % 2 === 1) ? (-this._mapTileSize.height / 2) : 0; 650 return cc.p(pos.x * this._mapTileSize.width * 3 / 4, 651 (this._layerSize.height - pos.y - 1) * this._mapTileSize.height + diffY); 652 }, 653 654 _calculateLayerOffset:function (pos) { 655 var ret = cc.p(0,0); 656 switch (this.layerOrientation) { 657 case cc.TMX_ORIENTATION_ORTHO: 658 ret = cc.p(pos.x * this._mapTileSize.width, -pos.y * this._mapTileSize.height); 659 break; 660 case cc.TMX_ORIENTATION_ISO: 661 ret = cc.p((this._mapTileSize.width / 2) * (pos.x - pos.y), 662 (this._mapTileSize.height / 2 ) * (-pos.x - pos.y)); 663 break; 664 case cc.TMX_ORIENTATION_HEX: 665 if(pos.x !== 0 || pos.y !== 0) 666 cc.log("offset for hexagonal map not implemented yet"); 667 break; 668 } 669 return ret; 670 }, 671 672 _updateTileForGID:function (gid, pos) { 673 if (!this._texGrids[gid]) { 674 return; 675 } 676 677 var idx = 0 | (pos.x + pos.y * this._layerSize.width); 678 if (idx < this.tiles.length) { 679 this.tiles[idx] = gid; 680 } 681 }, 682 683 //The layer recognizes some special properties, like cc_vertez 684 _parseInternalProperties:function () { 685 // if cc_vertex=automatic, then tiles will be rendered using vertexz 686 var vertexz = this.getProperty("cc_vertexz"); 687 if (vertexz) { 688 if (vertexz === "automatic") { 689 this._useAutomaticVertexZ = true; 690 var alphaFuncVal = this.getProperty("cc_alpha_func"); 691 var alphaFuncValue = 0; 692 if (alphaFuncVal) 693 alphaFuncValue = parseFloat(alphaFuncVal); 694 695 if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) { //todo: need move to WebGL render cmd 696 this.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_SPRITE_POSITION_TEXTURECOLORALPHATEST); 697 // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison 698 this.shaderProgram.use(); 699 this.shaderProgram.setUniformLocationWith1f(cc.UNIFORM_ALPHA_TEST_VALUE_S, alphaFuncValue); 700 } 701 } else 702 this._vertexZvalue = parseInt(vertexz, 10); 703 } 704 }, 705 706 _setupTileSprite:function (sprite, pos, gid) { 707 var z = pos.x + pos.y * this._layerSize.width; 708 var posInPixel = this.getPositionAt(pos); 709 sprite.setPosition(posInPixel); 710 sprite.setVertexZ(this._vertexZForPos(pos)); 711 sprite.setAnchorPoint(0, 0); 712 sprite.setOpacity(this._opacity); 713 sprite.setFlippedX(false); 714 sprite.setFlippedY(false); 715 sprite.setRotation(0.0); 716 717 // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles. 718 if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) { 719 // put the anchor in the middle for ease of rotation. 720 sprite.setAnchorPoint(0.5, 0.5); 721 sprite.setPosition(posInPixel.x + sprite.width/2, posInPixel.y + sprite.height/2); 722 723 var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0; 724 // handle the 4 diagonally flipped states. 725 if (flag === cc.TMX_TILE_HORIZONTAL_FLAG) 726 sprite.setRotation(90); 727 else if (flag === cc.TMX_TILE_VERTICAL_FLAG) 728 sprite.setRotation(270); 729 else if (flag === (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) { 730 sprite.setRotation(90); 731 sprite.setFlippedX(true); 732 } else { 733 sprite.setRotation(270); 734 sprite.setFlippedX(true); 735 } 736 } else { 737 if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) { 738 sprite.setFlippedX(true); 739 } 740 if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0) { 741 sprite.setFlippedY(true); 742 } 743 } 744 }, 745 746 _vertexZForPos:function (x, y) { 747 if (y === undefined) { 748 y = x.y; 749 x = x.x; 750 } 751 var ret = 0; 752 var maxVal = 0; 753 if (this._useAutomaticVertexZ) { 754 switch (this.layerOrientation) { 755 case cc.TMX_ORIENTATION_ISO: 756 maxVal = this._layerSize.width + this._layerSize.height; 757 ret = -(maxVal - (x + y)); 758 break; 759 case cc.TMX_ORIENTATION_ORTHO: 760 ret = -(this._layerSize.height - y); 761 break; 762 case cc.TMX_ORIENTATION_HEX: 763 cc.log("TMX Hexa zOrder not supported"); 764 break; 765 default: 766 cc.log("TMX invalid value"); 767 break; 768 } 769 } else { 770 ret = this._vertexZvalue; 771 } 772 return ret; 773 } 774 }); 775 776 var _p = cc.TMXLayer.prototype; 777 778 // Extended properties 779 /** @expose */ 780 _p.layerWidth; 781 cc.defineGetterSetter(_p, "layerWidth", _p._getLayerWidth, _p._setLayerWidth); 782 /** @expose */ 783 _p.layerHeight; 784 cc.defineGetterSetter(_p, "layerHeight", _p._getLayerHeight, _p._setLayerHeight); 785 /** @expose */ 786 _p.tileWidth; 787 cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth); 788 /** @expose */ 789 _p.tileHeight; 790 cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight); 791 792 793 /** 794 * Creates a cc.TMXLayer with an tile set info, a layer info and a map info 795 * @deprecated since v3.0 please use new cc.TMXLayer(tilesetInfo, layerInfo, mapInfo) instead. 796 * @param {cc.TMXTilesetInfo} tilesetInfo 797 * @param {cc.TMXLayerInfo} layerInfo 798 * @param {cc.TMXMapInfo} mapInfo 799 * @return {cc.TMXLayer|Null} 800 */ 801 cc.TMXLayer.create = function (tilesetInfo, layerInfo, mapInfo) { 802 return new cc.TMXLayer(tilesetInfo, layerInfo, mapInfo); 803 }; 804