1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga 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 cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ 49 //size of the layer in tiles 50 _layerSize:cc.SizeZero(), 51 _mapTileSize:cc.SizeZero(), 52 _tiles:null, 53 _tileSet:null, 54 _layerOrientation:null, 55 _properties:null, 56 //name of the layer 57 _layerName:"", 58 //TMX Layer supports opacity 59 _opacity:255, 60 _minGID:null, 61 _maxGID:null, 62 //Only used when vertexZ is used 63 _vertexZvalue:null, 64 _useAutomaticVertexZ:null, 65 _alphaFuncValue:null, 66 //used for optimization 67 _reusedTile:null, 68 _atlasIndexArray:null, 69 //used for retina display 70 _contentScaleFactor:null, 71 72 /** 73 * Constructor 74 */ 75 ctor:function () { 76 this._super(); 77 this._children = []; 78 this._descendants = []; 79 this._isUseCache = true; 80 this._layerSize = cc.p(0, 0); 81 this._mapTileSize = cc.p(0, 0); 82 }, 83 84 /** 85 * @return {cc.Size} 86 */ 87 getLayerSize:function () { 88 return this._layerSize; 89 }, 90 91 /** 92 * @param {cc.Size} Var 93 */ 94 setLayerSize:function (Var) { 95 this._layerSize = Var; 96 }, 97 98 /** 99 * Size of the map's tile (could be different from the tile's size) 100 * @return {cc.Size} 101 */ 102 getMapTileSize:function () { 103 return this._mapTileSize; 104 }, 105 106 /** 107 * @param {cc.Size} Var 108 */ 109 setMapTileSize:function (Var) { 110 this._mapTileSize = Var; 111 }, 112 113 /** 114 * Pointer to the map of tiles 115 * @return {Array} 116 */ 117 getTiles:function () { 118 return this._tiles; 119 }, 120 121 /** 122 * @param {Array} Var 123 */ 124 setTiles:function (Var) { 125 this._tiles = Var; 126 }, 127 128 /** 129 * Tile set information for the layer 130 * @return {cc.TMXTilesetInfo} 131 */ 132 getTileSet:function () { 133 return this._tileSet; 134 }, 135 136 /** 137 * @param {cc.TMXTilesetInfo} Var 138 */ 139 setTileSet:function (Var) { 140 this._tileSet = Var; 141 }, 142 143 /** 144 * Layer orientation, which is the same as the map orientation 145 * @return {Number} 146 */ 147 getLayerOrientation:function () { 148 return this._layerOrientation; 149 }, 150 151 /** 152 * @param {Number} Var 153 */ 154 setLayerOrientation:function (Var) { 155 this._layerOrientation = Var; 156 }, 157 158 /** 159 * properties from the layer. They can be added using Tiled 160 * @return {Array} 161 */ 162 getProperties:function () { 163 return this._properties; 164 }, 165 166 /** 167 * @param {Array} Var 168 */ 169 setProperties:function (Var) { 170 this._properties = Var; 171 }, 172 173 /** 174 * Initializes a cc.TMXLayer with a tileset info, a layer info and a map info 175 * @param {cc.TMXTilesetInfo} tilesetInfo 176 * @param {cc.TMXLayerInfo} layerInfo 177 * @param {cc.TMXMapInfo} mapInfo 178 * @return {Boolean} 179 */ 180 initWithTilesetInfo:function (tilesetInfo, layerInfo, mapInfo) { 181 // XXX: is 35% a good estimate ? 182 var size = layerInfo._layerSize; 183 var totalNumberOfTiles = parseInt(size.width * size.height); 184 var capacity = totalNumberOfTiles * 0.35 + 1; // 35 percent is occupied ? 185 186 if (tilesetInfo) { 187 var texture = cc.TextureCache.getInstance().addImage(tilesetInfo.sourceImage.toString()); 188 } 189 if (this.initWithTexture(texture, capacity)) { 190 // layerInfo 191 this._layerName = layerInfo.name; 192 this._layerSize = size; 193 this._tiles = layerInfo._tiles; 194 this._minGID = layerInfo._minGID; 195 this._maxGID = layerInfo._maxGID; 196 this._opacity = layerInfo._opacity; 197 this.setProperties(layerInfo.getProperties()); 198 this._contentScaleFactor = cc.Director.getInstance().getContentScaleFactor(); 199 200 // tilesetInfo 201 this._tileSet = tilesetInfo; 202 203 // mapInfo 204 this._mapTileSize = mapInfo.getTileSize(); 205 this._layerOrientation = mapInfo.getOrientation(); 206 207 // offset (after layer orientation is set); 208 var offset = this._calculateLayerOffset(layerInfo.offset); 209 this.setPosition(cc.POINT_PIXELS_TO_POINTS(offset)); 210 211 this._atlasIndexArray = []; 212 this.setContentSize(cc.SIZE_PIXELS_TO_POINTS(cc.size(this._layerSize.width * this._mapTileSize.width, 213 this._layerSize.height * this._mapTileSize.height))); 214 this._useAutomaticVertexZ = false; 215 this._vertexZvalue = 0; 216 return true; 217 } 218 return false; 219 }, 220 221 /** 222 * <p>Dealloc the map that contains the tile position from memory. <br /> 223 * Unless you want to know at runtime the tiles positions, you can safely call this method. <br /> 224 * If you are going to call layer.getTileGIDAt() then, don't release the map</p> 225 */ 226 releaseMap:function () { 227 if (this._tiles) { 228 this._tiles = null; 229 } 230 231 if (this._atlasIndexArray) { 232 this._atlasIndexArray = null; 233 } 234 }, 235 236 /** 237 * <p>Returns the tile (cc.Sprite) at a given a tile coordinate. <br/> 238 * The returned cc.Sprite will be already added to the cc.TMXLayer. Don't add it again.<br/> 239 * The cc.Sprite can be treated like any other cc.Sprite: rotated, scaled, translated, opacity, color, etc. <br/> 240 * You can remove either by calling: <br/> 241 * - layer.removeChild(sprite, cleanup); <br/> 242 * - or layer.removeTileAt(ccp(x,y)); </p> 243 * @param {cc.Point} pos 244 * @return {cc.Sprite} 245 */ 246 getTileAt:function (pos) { 247 cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position"); 248 cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released"); 249 250 var tile = null; 251 var gid = this.getTileGIDAt(pos); 252 253 // if GID == 0, then no tile is present 254 if (gid) { 255 var z = pos.x + pos.y * this._layerSize.width; 256 257 tile = this.getChildByTag(z); 258 259 // tile not created yet. create it 260 if (!tile) { 261 var rect = this._tileSet.rectForGID(gid); 262 rect = cc.RECT_PIXELS_TO_POINTS(rect); 263 264 tile = new cc.Sprite(); 265 tile.initWithTexture(this.getTexture(), rect); 266 tile.setBatchNode(this); 267 tile.setPosition(this.getPositionAt(pos)); 268 tile.setVertexZ(this._vertexZForPos(pos)); 269 tile.setAnchorPoint(cc.PointZero()); 270 tile.setOpacity(this._opacity); 271 272 var indexForZ = this._atlasIndexForExistantZ(z); 273 this.addSpriteWithoutQuad(tile, indexForZ, z); 274 } 275 } 276 return tile; 277 }, 278 // XXX: deprecated 279 // tileAt:getTileAt, 280 281 /** 282 * Returns the tile gid at a given tile coordinate. <br /> 283 * if it returns 0, it means that the tile is empty. <br /> 284 * This method requires the the tile map has not been previously released (eg. don't call layer.releaseMap())<br /> 285 * @param {cc.Point} pos 286 * @return {Number} 287 */ 288 getTileGIDAt:function (pos) { 289 cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position"); 290 cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released"); 291 292 var idx = pos.x + pos.y * this._layerSize.width; 293 // Bits on the far end of the 32-bit global tile ID are used for tile flags 294 var tile = this._tiles[idx]; 295 296 return (tile & cc.TMX_TILE_ALL_FLAGS_MASK) >>> 0; 297 }, 298 // XXX: deprecated 299 // tileGIDAt:getTileGIDAt, 300 301 /** 302 * lipped tiles can be changed dynamically 303 * @param {cc.Point} pos 304 * @return {Number} 305 */ 306 getTileFlagsAt:function (pos) { 307 cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position"); 308 cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released"); 309 310 var idx = pos.x + pos.y * this._layerSize.width; 311 // Bits on the far end of the 32-bit global tile ID are used for tile flags 312 var tile = this._tiles[idx]; 313 314 return (tile & cc.TMX_TILE_ALL_FLAGS) >>> 0; 315 }, 316 // XXX: deprecated 317 // tileFlagAt:getTileFlagsAt, 318 319 /** 320 * <p>Sets the tile gid (gid = tile global id) at a given tile coordinate.<br /> 321 * The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor . Tileset Mgr +1.<br /> 322 * If a tile is already placed at that position, then it will be removed.</p> 323 * @param {Number} gid 324 * @param {cc.Point} pos 325 * @param {Number} flags 326 */ 327 setTileGID:function (gid, pos, flags) { 328 cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position"); 329 cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released"); 330 cc.Assert(gid !== 0 || !(gid >= this._tileSet.firstGid), "TMXLayer: invalid gid:" + gid); 331 332 this._setNodeDirtyForCache(); 333 334 var currentFlags = this.getTileFlagsAt(pos); 335 var currentGID = this.getTileGIDAt(pos); 336 337 if (currentGID != gid || currentFlags != flags) { 338 var gidAndFlags = (gid | flags) >>> 0; 339 // setting gid=0 is equal to remove the tile 340 if (gid == 0) { 341 this.removeTileAt(pos); 342 } else if (currentGID == 0) { // empty tile. create a new one 343 this._insertTileForGID(gidAndFlags, pos); 344 } else { // modifying an existing tile with a non-empty tile 345 var z = pos.x + pos.y * this._layerSize.width; 346 var sprite = this.getChildByTag(z); 347 if (sprite) { 348 var rect = this._tileSet.rectForGID(gid); 349 rect = cc.RECT_PIXELS_TO_POINTS(rect); 350 351 sprite.setTextureRect(rect, false, rect.size); 352 if (flags != null) { 353 this._setupTileSprite(sprite, pos, gidAndFlags); 354 } 355 this._tiles[z] = gidAndFlags; 356 } else { 357 this._updateTileForGID(gidAndFlags, pos); 358 } 359 } 360 } 361 }, 362 363 /** 364 * Removes a tile at given tile coordinate 365 * @param {cc.Point} pos 366 */ 367 removeTileAt:function (pos) { 368 cc.Assert(pos.x < this._layerSize.width && pos.y < this._layerSize.height && pos.x >= 0 && pos.y >= 0, "TMXLayer: invalid position"); 369 cc.Assert(this._tiles && this._atlasIndexArray, "TMXLayer: the tiles map has been released"); 370 371 this._setNodeDirtyForCache(); 372 //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld()); 373 374 var gid = this.getTileGIDAt(pos); 375 376 if (gid) { 377 var z = pos.x + pos.y * this._layerSize.width; 378 var atlasIndex = this._atlasIndexForExistantZ(z); 379 // remove tile from GID map 380 this._tiles[z] = 0; 381 382 // remove tile from atlas position array 383 cc.ArrayRemoveObjectAtIndex(this._atlasIndexArray, atlasIndex); 384 385 // remove it from sprites and/or texture atlas 386 var sprite = this.getChildByTag(z); 387 388 if (sprite) { 389 this.removeChild(sprite, true); 390 } 391 else { 392 this._textureAtlas.removeQuadAtIndex(atlasIndex); 393 394 // update possible children 395 if (this._children) { 396 for (var i = 0, len = this._children.length; i < len; i++) { 397 var child = this._children[i]; 398 if (child) { 399 var ai = child.getAtlasIndex(); 400 if (ai >= atlasIndex) { 401 child.setAtlasIndex(ai - 1); 402 } 403 } 404 } 405 } 406 } 407 } 408 }, 409 410 /** 411 * Returns the position in pixels of a given tile coordinate 412 * @param {cc.Point} pos 413 * @return {cc.Point} 414 */ 415 getPositionAt:function (pos) { 416 var ret = cc.PointZero(); 417 switch (this._layerOrientation) { 418 case cc.TMX_ORIENTATION_ORTHO: 419 ret = this._positionForOrthoAt(pos); 420 break; 421 case cc.TMX_ORIENTATION_ISO: 422 ret = this._positionForIsoAt(pos); 423 break; 424 case cc.TMX_ORIENTATION_HEX: 425 ret = this._positionForHexAt(pos); 426 break; 427 } 428 ret = cc.POINT_PIXELS_TO_POINTS(ret); 429 return ret; 430 }, 431 // XXX: Deprecated. For backward compatibility only 432 // positionAt:getPositionAt, 433 434 /** 435 * Return the value for the specific property name 436 * @param {String} propertyName 437 * @return {Number} 438 * //todo 439 */ 440 getProperty:function (propertyName) { 441 return this._properties[propertyName]; 442 }, 443 // XXX: Deprecated. For backward compatibility only 444 // propertyNamed:getProperty, 445 446 /** 447 * Creates the tiles 448 */ 449 setupTiles:function () { 450 // Optimization: quick hack that sets the image size on the tileset 451 var textureCache = this._textureAtlas.getTexture(); 452 this._tileSet.imageSize = cc.size(textureCache.width, textureCache.height); 453 454 // By default all the tiles are aliased 455 // pros: 456 // - easier to render 457 // cons: 458 // - difficult to scale / rotate / etc. 459 //this._textureAtlas.getTexture().setAliasTexParameters(); 460 461 // Parse cocos2d properties 462 this._parseInternalProperties(); 463 this._setNodeDirtyForCache(); 464 //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld()); 465 466 for (var y = 0; y < this._layerSize.height; y++) { 467 for (var x = 0; x < this._layerSize.width; x++) { 468 var pos = x + this._layerSize.width * y; 469 var gid = this._tiles[pos]; 470 471 // XXX: gid == 0 -. empty tile 472 if (gid != 0) { 473 this._appendTileForGID(gid, cc.p(x, y)); 474 // Optimization: update min and max GID rendered by the layer 475 this._minGID = Math.min(gid, this._minGID); 476 this._maxGID = Math.max(gid, this._maxGID); 477 } 478 } 479 } 480 // console.log(this._maxGID , this._tileSet.firstGid , this._minGID , this._tileSet.firstGid) 481 cc.Assert((this._maxGID >= this._tileSet.firstGid && this._minGID >= this._tileSet.firstGid), "TMX: Only 1 tileset per layer is supported"); 482 }, 483 484 /** 485 * cc.TMXLayer doesn't support adding a cc.Sprite manually. 486 * @warning addChild(child); is not supported on cc.TMXLayer. Instead of setTileGID. 487 * @param {cc.Node} child 488 */ 489 addChild:function (child) { 490 cc.Assert(0, "addChild: is not supported on cc.TMXLayer. Instead use setTileGID:at:/tileAt:"); 491 }, 492 493 /** 494 * Remove child 495 * @param {cc.Node} child 496 * @param {Boolean} cleanup 497 */ 498 removeChild:function (child, cleanup) { 499 var sprite = child; 500 501 // allows removing nil objects 502 if (!sprite) 503 return; 504 505 cc.Assert(cc.ArrayContainsObject(this._children, sprite), "Tile does not belong to TMXLayer"); 506 507 this._setNodeDirtyForCache(); 508 //this._addDirtyRegionToDirector(this.getBoundingBoxToWorld()); 509 var atlasIndex = cc.ArrayGetIndexOfObject(this._children, sprite); 510 var zz = this._atlasIndexArray[atlasIndex]; 511 this._tiles[zz] = 0; 512 cc.ArrayRemoveObjectAtIndex(this._atlasIndexArray, atlasIndex); 513 this._super(sprite, cleanup); 514 }, 515 516 /** 517 * @return {String} 518 */ 519 getLayerName:function () { 520 return this._layerName.toString(); 521 }, 522 523 /** 524 * @param {String} layerName 525 */ 526 setLayerName:function (layerName) { 527 this._layerName = layerName; 528 }, 529 530 _positionForIsoAt:function (pos) { 531 return cc.p(this._mapTileSize.width / 2 * ( this._layerSize.width + pos.x - pos.y - 1), 532 this._mapTileSize.height / 2 * (( this._layerSize.height * 2 - pos.x - pos.y) - 2)); 533 }, 534 535 _positionForOrthoAt:function (pos) { 536 return cc.p(pos.x * this._mapTileSize.width, 537 (this._layerSize.height - pos.y - 1) * this._mapTileSize.height); 538 }, 539 540 _positionForHexAt:function (pos) { 541 var diffY = 0; 542 if (pos.x % 2 == 1) { 543 diffY = -this._mapTileSize.height / 2; 544 } 545 546 return cc.p(pos.x * this._mapTileSize.width * 3 / 4, 547 (this._layerSize.height - pos.y - 1) * this._mapTileSize.height + diffY); 548 }, 549 550 _calculateLayerOffset:function (pos) { 551 var ret = cc.PointZero(); 552 switch (this._layerOrientation) { 553 case cc.TMX_ORIENTATION_ORTHO: 554 ret = cc.p(pos.x * this._mapTileSize.width, -pos.y * this._mapTileSize.height); 555 break; 556 case cc.TMX_ORIENTATION_ISO: 557 ret = cc.p((this._mapTileSize.width / 2) * (pos.x - pos.y), 558 (this._mapTileSize.height / 2 ) * (-pos.x - pos.y)); 559 break; 560 case cc.TMX_ORIENTATION_HEX: 561 ret = cc.p(0, 0); 562 cc.log("cocos2d:offset for hexagonal map not implemented yet"); 563 break; 564 } 565 return ret; 566 }, 567 568 _appendTileForGID:function (gid, pos) { 569 var rect = this._tileSet.rectForGID(gid); 570 rect = cc.RECT_PIXELS_TO_POINTS(rect); 571 572 var z = pos.x + pos.y * this._layerSize.width; 573 var tile = this._reusedTileWithRect(rect); 574 575 this._setupTileSprite(tile, pos, gid); 576 577 // optimization: 578 // The difference between _appendTileForGID and _insertTileForGID is that append is faster, since 579 // it appends the tile at the end of the texture atlas 580 //todo fix 581 var indexForZ = this._atlasIndexArray.length; 582 583 // don't add it using the "standard" way. 584 this.addQuadFromSprite(tile, indexForZ); 585 586 // append should be after addQuadFromSprite since it modifies the quantity values 587 this._atlasIndexArray = cc.ArrayAppendObjectToIndex(this._atlasIndexArray, z, indexForZ); 588 return tile; 589 }, 590 591 _insertTileForGID:function (gid, pos) { 592 var rect = this._tileSet.rectForGID(gid); 593 rect = cc.RECT_PIXELS_TO_POINTS(rect); 594 595 var z = parseInt(pos.x + pos.y * this._layerSize.width); 596 var tile = this._reusedTileWithRect(rect); 597 this._setupTileSprite(tile, pos, gid); 598 599 // get atlas index 600 var indexForZ = this._atlasIndexForNewZ(z); 601 602 // Optimization: add the quad without adding a child 603 this.addQuadFromSprite(tile, indexForZ); 604 605 // insert it into the local atlasindex array 606 this._atlasIndexArray = cc.ArrayAppendObjectToIndex(this._atlasIndexArray, z, indexForZ); 607 // update possible children 608 if (this._children) { 609 for (var i = 0, len = this._children.length; i < len; i++) { 610 var child = this._children[i]; 611 if (child) { 612 var ai = child.getAtlasIndex(); 613 if (ai >= indexForZ) { 614 child.setAtlasIndex(ai + 1); 615 } 616 } 617 } 618 } 619 this._tiles[z] = gid; 620 return tile; 621 }, 622 623 _updateTileForGID:function (gid, pos) { 624 var rect = this._tileSet.rectForGID(gid); 625 rect = cc.rect(rect.origin.x / this._contentScaleFactor, rect.origin.y / this._contentScaleFactor, 626 rect.size.width / this._contentScaleFactor, rect.size.height / this._contentScaleFactor); 627 var z = pos.x + pos.y * this._layerSize.width; 628 629 var tile = this._reusedTileWithRect(rect); 630 631 this._setupTileSprite(tile, pos, gid); 632 633 // get atlas index 634 var indexForZ = this._atlasIndexForExistantZ(z); 635 tile.setAtlasIndex(indexForZ); 636 tile.setDirty(true); 637 tile.updateTransform(); 638 this._tiles[z] = gid; 639 640 return tile; 641 }, 642 643 //The layer recognizes some special properties, like cc_vertez 644 _parseInternalProperties:function () { 645 // if cc_vertex=automatic, then tiles will be rendered using vertexz 646 647 var vertexz = this.getProperty("cc_vertexz"); 648 if (vertexz) { 649 if (vertexz == "automatic") { 650 this._useAutomaticVertexZ = true; 651 var alphaFuncVal = this.getProperty("cc_alpha_func"); 652 var alphaFuncValue = 0; 653 654 //todo webgl 655 //this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(kcc.Shader_PositionTextureColorAlphaTest)); 656 //var alphaValueLocation = glGetUniformLocation(getShaderProgram().getProgram(), kcc.UniformAlphaTestValue); 657 // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison 658 //this.getShaderProgram().setUniformLocationWith1f(alphaValueLocation, alphaFuncValue); 659 } 660 else { 661 this._vertexZvalue = parseInt(vertexz, 10); 662 } 663 } 664 665 var alphaFuncVal = this.getProperty("cc_alpha_func"); 666 if (alphaFuncVal) { 667 this._alphaFuncValue = parseInt(alphaFuncVal, 10); 668 } 669 }, 670 671 _setupTileSprite:function (sprite, pos, gid) { 672 var z = pos.x + pos.y * this._layerSize.width; 673 sprite.setPosition(this.getPositionAt(pos)); 674 //sprite.setVertexZ(this._vertexZForPos(pos)); 675 sprite.setAnchorPoint(cc.PointZero()); 676 sprite.setOpacity(this._opacity); 677 sprite.setTag(z); 678 sprite.setFlipX(false); 679 sprite.setFlipY(false); 680 681 // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles. 682 683 if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) { 684 // put the anchor in the middle for ease of rotation. 685 sprite.setAnchorPoint(cc.p(0.5, 0.5)); 686 sprite.setPosition(cc.p(this.getPositionAt(pos).x + sprite.getContentSize().height / 2, 687 this.getPositionAt(pos).y + sprite.getContentSize().width / 2)); 688 689 var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0; 690 // handle the 4 diagonally flipped states. 691 if (flag == cc.TMX_TILE_HORIZONTAL_FLAG) { 692 sprite.setRotation(90); 693 } 694 else if (flag == cc.TMX_TILE_VERTICAL_FLAG) { 695 sprite.setRotation(270); 696 } 697 else if (flag == (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) { 698 sprite.setRotation(90); 699 sprite.setFlipX(true); 700 } 701 else { 702 sprite.setRotation(270); 703 sprite.setFlipX(true); 704 } 705 } 706 else { 707 if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) { 708 sprite.setFlipX(true); 709 } 710 711 if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0) { 712 sprite.setFlipY(true); 713 } 714 } 715 }, 716 717 _reusedTileWithRect:function (rect) { 718 this._reusedTile = new cc.Sprite(); 719 this._reusedTile.initWithTexture(this._textureAtlas.getTexture(), rect, false); 720 this._reusedTile.setBatchNode(this); 721 this._reusedTile.setParent(this); 722 723 return this._reusedTile; 724 }, 725 726 _vertexZForPos:function (pos) { 727 var ret = 0; 728 var maxVal = 0; 729 if (this._useAutomaticVertexZ) { 730 switch (this._layerOrientation) { 731 case cc.TMX_ORIENTATION_ISO: 732 maxVal = this._layerSize.width + this._layerSize.height; 733 ret = -(maxVal - (pos.x + pos.y)); 734 break; 735 case cc.TMX_ORIENTATION_ORTHO: 736 ret = -(this._layerSize.height - pos.y); 737 break; 738 case cc.TMX_ORIENTATION_HEX: 739 cc.Assert(0, "TMX Hexa zOrder not supported"); 740 break; 741 default: 742 cc.Assert(0, "TMX invalid value"); 743 break; 744 } 745 } 746 else { 747 ret = this._vertexZvalue; 748 } 749 return ret; 750 }, 751 752 _atlasIndexForExistantZ:function (z) { 753 var item; 754 if (this._atlasIndexArray) { 755 for (var i = 0; i < this._atlasIndexArray.length; i++) { 756 item = this._atlasIndexArray[i]; 757 if (item == z) { 758 break; 759 } 760 } 761 } 762 cc.Assert(item != null, "TMX atlas index not found. Shall not happen"); 763 return i; 764 }, 765 766 _atlasIndexForNewZ:function (z) { 767 for (var i = 0; i < this._atlasIndexArray.length; i++) { 768 var val = this._atlasIndexArray[i]; 769 if (z < val) 770 break; 771 } 772 return i; 773 } 774 }); 775 776 /** 777 * Creates a cc.TMXLayer with an tile set info, a layer info and a map info 778 * @param {cc.TMXTilesetInfo} tilesetInfo 779 * @param {cc.TMXLayerInfo} layerInfo 780 * @param {cc.TMXMapInfo} mapInfo 781 * @return {cc.TMXLayer|Null} 782 */ 783 cc.TMXLayer.create = function (tilesetInfo, layerInfo, mapInfo) { 784 var ret = new cc.TMXLayer(); 785 if (ret.initWithTilesetInfo(tilesetInfo, layerInfo, mapInfo)) { 786 return ret; 787 } 788 return null; 789 }; 790