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 * @constant 29 * @type Number 30 */ 31 cc.TMX_PROPERTY_NONE = 0; 32 33 /** 34 * @constant 35 * @type Number 36 */ 37 cc.TMX_PROPERTY_MAP = 1; 38 39 /** 40 * @constant 41 * @type Number 42 */ 43 cc.TMX_PROPERTY_LAYER = 2; 44 45 /** 46 * @constant 47 * @type Number 48 */ 49 cc.TMX_PROPERTY_OBJECTGROUP = 3; 50 51 /** 52 * @constant 53 * @type Number 54 */ 55 cc.TMX_PROPERTY_OBJECT = 4; 56 57 /** 58 * @constant 59 * @type Number 60 */ 61 cc.TMX_PROPERTY_TILE = 5; 62 63 /** 64 * @constant 65 * @type Number 66 */ 67 cc.TMX_TILE_HORIZONTAL_FLAG = 0x80000000; 68 69 70 /** 71 * @constant 72 * @type Number 73 */ 74 cc.TMX_TILE_VERTICAL_FLAG = 0x40000000; 75 76 /** 77 * @constant 78 * @type Number 79 */ 80 cc.TMX_TILE_DIAGONAL_FLAG = 0x20000000; 81 82 /** 83 * @constant 84 * @type Number 85 */ 86 cc.TMX_TILE_FLIPPED_ALL = (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_DIAGONAL_FLAG) >>> 0; 87 88 /** 89 * @constant 90 * @type Number 91 */ 92 cc.TMX_TILE_FLIPPED_MASK = (~(cc.TMX_TILE_FLIPPED_ALL)) >>> 0; 93 94 // Bits on the far end of the 32-bit global tile ID (GID's) are used for tile flags 95 96 /** 97 * <p>cc.TMXLayerInfo contains the information about the layers like: <br /> 98 * - Layer name<br /> 99 * - Layer size <br /> 100 * - Layer opacity at creation time (it can be modified at runtime) <br /> 101 * - Whether the layer is visible (if it's not visible, then the CocosNode won't be created) <br /> 102 * <br /> 103 * This information is obtained from the TMX file.</p> 104 * @class 105 * @extends cc.Class 106 * 107 * @property {Array} properties - Properties of the layer info. 108 */ 109 cc.TMXLayerInfo = cc.Class.extend(/** @lends cc.TMXLayerInfo# */{ 110 properties:null, 111 112 name:"", 113 _layerSize:null, 114 _tiles:null, 115 visible:null, 116 _opacity:null, 117 ownTiles:true, 118 _minGID:100000, 119 _maxGID:0, 120 offset:null, 121 122 ctor:function () { 123 this.properties = []; 124 this.name = ""; 125 this._layerSize = null; 126 this._tiles = []; 127 this.visible = true; 128 this._opacity = 0; 129 this.ownTiles = true; 130 this._minGID = 100000; 131 this._maxGID = 0; 132 this.offset = cc.p(0,0); 133 }, 134 135 /** 136 * @return {Array} 137 */ 138 getProperties:function () { 139 return this.properties; 140 }, 141 142 /** 143 * @param {object} value 144 */ 145 setProperties:function (value) { 146 this.properties = value; 147 } 148 }); 149 150 /** 151 * <p>cc.TMXTilesetInfo contains the information about the tilesets like: <br /> 152 * - Tileset name<br /> 153 * - Tileset spacing<br /> 154 * - Tileset margin<br /> 155 * - size of the tiles<br /> 156 * - Image used for the tiles<br /> 157 * - Image size<br /> 158 * 159 * This information is obtained from the TMX file. </p> 160 * @class 161 * @extends cc.Class 162 */ 163 cc.TMXTilesetInfo = cc.Class.extend(/** @lends cc.TMXTilesetInfo# */{ 164 165 /** 166 * Tileset name 167 */ 168 name:"", 169 170 /** 171 * First grid 172 */ 173 firstGid:0, 174 _tileSize:null, 175 176 /** 177 * Spacing 178 */ 179 spacing:0, 180 181 /** 182 * Margin 183 */ 184 margin:0, 185 186 /** 187 * Filename containing the tiles (should be sprite sheet / texture atlas) 188 */ 189 sourceImage:"", 190 191 /** 192 * Size in pixels of the image 193 */ 194 imageSize:null, 195 196 ctor:function () { 197 this._tileSize = cc.size(0, 0); 198 this.imageSize = cc.size(0, 0); 199 }, 200 201 /** 202 * @param {Number} gid 203 * @return {cc.Rect} 204 */ 205 rectForGID:function (gid) { 206 var rect = cc.rect(0, 0, 0, 0); 207 rect.width = this._tileSize.width; 208 rect.height = this._tileSize.height; 209 gid &= cc.TMX_TILE_FLIPPED_MASK; 210 gid = gid - parseInt(this.firstGid, 10); 211 var max_x = parseInt((this.imageSize.width - this.margin * 2 + this.spacing) / (this._tileSize.width + this.spacing), 10); 212 rect.x = parseInt((gid % max_x) * (this._tileSize.width + this.spacing) + this.margin, 10); 213 rect.y = parseInt(parseInt(gid / max_x, 10) * (this._tileSize.height + this.spacing) + this.margin, 10); 214 return rect; 215 } 216 }); 217 218 /** 219 * <p>cc.TMXMapInfo contains the information about the map like: <br/> 220 *- Map orientation (hexagonal, isometric or orthogonal)<br/> 221 *- Tile size<br/> 222 *- Map size</p> 223 * 224 * <p>And it also contains: <br/> 225 * - Layers (an array of TMXLayerInfo objects)<br/> 226 * - Tilesets (an array of TMXTilesetInfo objects) <br/> 227 * - ObjectGroups (an array of TMXObjectGroupInfo objects) </p> 228 * 229 * <p>This information is obtained from the TMX file. </p> 230 * @class 231 * @extends cc.saxParser 232 * 233 * @property {Array} properties - Properties of the map info. 234 * @property {Number} orientation - Map orientation. 235 * @property {Object} parentElement - Parent element. 236 * @property {Number} parentGID - Parent GID. 237 * @property {Object} layerAttrs - Layer attributes. 238 * @property {Boolean} storingCharacters - Is reading storing characters stream. 239 * @property {String} tmxFileName - TMX file name. 240 * @property {String} currentString - Current string stored from characters stream. 241 * @property {Number} mapWidth - Width of the map 242 * @property {Number} mapHeight - Height of the map 243 * @property {Number} tileWidth - Width of a tile 244 * @property {Number} tileHeight - Height of a tile 245 */ 246 cc.TMXMapInfo = cc.SAXParser.extend(/** @lends cc.TMXMapInfo# */{ 247 properties:null, 248 orientation:null, 249 parentElement:null, 250 parentGID:null, 251 layerAttrs:0, 252 storingCharacters:false, 253 tmxFileName:null, 254 currentString:null, 255 256 _objectGroups:null, 257 _mapSize:null, 258 _tileSize:null, 259 _layers:null, 260 _tilesets:null, 261 // tile properties 262 _tileProperties:null, 263 _resources:"", 264 _currentFirstGID:0, 265 266 /** 267 * Creates a TMX Format with a tmx file or content string <br/> 268 * Constructor of cc.TMXMapInfo 269 * @param {String} tmxFile fileName or content string 270 * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required. 271 * @example 272 * 1. 273 * //create a TMXMapInfo with file name 274 * var tmxMapInfo = cc.TMXMapInfo.create("res/orthogonal-test1.tmx"); 275 * 2. 276 * //create a TMXMapInfo with content string and resource path 277 * var resources = "res/TileMaps"; 278 * var filePath = "res/TileMaps/orthogonal-test1.tmx"; 279 * var xmlStr = cc.loader.getRes(filePath); 280 * var tmxMapInfo = cc.TMXMapInfo.create(xmlStr, resources); 281 */ 282 ctor:function (tmxFile, resourcePath) { 283 cc.SAXParser.prototype.ctor.apply(this); 284 this._mapSize = cc.size(0, 0); 285 this._tileSize = cc.size(0, 0); 286 this._layers = []; 287 this._tilesets = []; 288 this._objectGroups = []; 289 this.properties = []; 290 this._tileProperties = {}; 291 292 this._currentFirstGID = 0; 293 294 if (resourcePath !== undefined) { 295 this.initWithXML(tmxFile,resourcePath); 296 } else if(tmxFile !== undefined){ 297 this.initWithTMXFile(tmxFile); 298 } 299 }, 300 /** 301 * @return {Number} 302 */ 303 getOrientation:function () { 304 return this.orientation; 305 }, 306 307 /** 308 * @param {Number} value 309 */ 310 setOrientation:function (value) { 311 this.orientation = value; 312 }, 313 314 /** 315 * Map width & height 316 * @return {cc.Size} 317 */ 318 getMapSize:function () { 319 return cc.size(this._mapSize.width,this._mapSize.height); 320 }, 321 322 /** 323 * @param {cc.Size} value 324 */ 325 setMapSize:function (value) { 326 this._mapSize.width = value.width; 327 this._mapSize.height = value.height; 328 }, 329 330 _getMapWidth: function () { 331 return this._mapSize.width; 332 }, 333 _setMapWidth: function (width) { 334 this._mapSize.width = width; 335 }, 336 _getMapHeight: function () { 337 return this._mapSize.height; 338 }, 339 _setMapHeight: function (height) { 340 this._mapSize.height = height; 341 }, 342 343 /** 344 * Tiles width & height 345 * @return {cc.Size} 346 */ 347 getTileSize:function () { 348 return cc.size(this._tileSize.width, this._tileSize.height); 349 }, 350 351 /** 352 * @param {cc.Size} value 353 */ 354 setTileSize:function (value) { 355 this._tileSize.width = value.width; 356 this._tileSize.height = value.height; 357 }, 358 359 _getTileWidth: function () { 360 return this._tileSize.width; 361 }, 362 _setTileWidth: function (width) { 363 this._tileSize.width = width; 364 }, 365 _getTileHeight: function () { 366 return this._tileSize.height; 367 }, 368 _setTileHeight: function (height) { 369 this._tileSize.height = height; 370 }, 371 372 /** 373 * Layers 374 * @return {Array} 375 */ 376 getLayers:function () { 377 return this._layers; 378 }, 379 380 /** 381 * @param {cc.TMXLayerInfo} value 382 */ 383 setLayers:function (value) { 384 this._layers.push(value); 385 }, 386 387 /** 388 * tilesets 389 * @return {Array} 390 */ 391 getTilesets:function () { 392 return this._tilesets; 393 }, 394 395 /** 396 * @param {cc.TMXTilesetInfo} value 397 */ 398 setTilesets:function (value) { 399 this._tilesets.push(value); 400 }, 401 402 /** 403 * ObjectGroups 404 * @return {Array} 405 */ 406 getObjectGroups:function () { 407 return this._objectGroups; 408 }, 409 410 /** 411 * @param {cc.TMXObjectGroup} value 412 */ 413 setObjectGroups:function (value) { 414 this._objectGroups.push(value); 415 }, 416 417 /** 418 * parent element 419 * @return {Object} 420 */ 421 getParentElement:function () { 422 return this.parentElement; 423 }, 424 425 /** 426 * @param {Object} value 427 */ 428 setParentElement:function (value) { 429 this.parentElement = value; 430 }, 431 432 /** 433 * parent GID 434 * @return {Number} 435 */ 436 getParentGID:function () { 437 return this.parentGID; 438 }, 439 440 /** 441 * @param {Number} value 442 */ 443 setParentGID:function (value) { 444 this.parentGID = value; 445 }, 446 447 /** 448 * Layer attribute 449 * @return {Object} 450 */ 451 getLayerAttribs:function () { 452 return this.layerAttrs; 453 }, 454 455 /** 456 * @param {Object} value 457 */ 458 setLayerAttribs:function (value) { 459 this.layerAttrs = value; 460 }, 461 462 /** 463 * Is reading storing characters stream 464 * @return {Boolean} 465 */ 466 getStoringCharacters:function () { 467 return this.storingCharacters; 468 }, 469 470 /** 471 * @param {Boolean} value 472 */ 473 setStoringCharacters:function (value) { 474 this.storingCharacters = value; 475 }, 476 477 /** 478 * Properties 479 * @return {Array} 480 */ 481 getProperties:function () { 482 return this.properties; 483 }, 484 485 /** 486 * @param {object} value 487 */ 488 setProperties:function (value) { 489 this.properties = value; 490 }, 491 492 /** 493 * Initializes a TMX format with a tmx file 494 * @param {String} tmxFile 495 * @return {Element} 496 */ 497 initWithTMXFile:function (tmxFile) { 498 this._internalInit(tmxFile, null); 499 return this.parseXMLFile(tmxFile); 500 }, 501 502 /** 503 * initializes a TMX format with an XML string and a TMX resource path 504 * @param {String} tmxString 505 * @param {String} resourcePath 506 * @return {Boolean} 507 */ 508 initWithXML:function (tmxString, resourcePath) { 509 this._internalInit(null, resourcePath); 510 return this.parseXMLString(tmxString); 511 }, 512 513 /** Initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file 514 * @param {String} tmxFile 515 * @param {boolean} [isXmlString=false] 516 * @return {Element} 517 */ 518 parseXMLFile:function (tmxFile, isXmlString) { 519 isXmlString = isXmlString || false; 520 var xmlStr = isXmlString ? tmxFile : cc.loader.getRes(tmxFile); 521 if(!xmlStr) throw "Please load the resource first : " + tmxFile; 522 523 var mapXML = this._parseXML(xmlStr); 524 var i, j; 525 526 // PARSE <map> 527 var map = mapXML.documentElement; 528 529 var version = map.getAttribute('version'); 530 var orientationStr = map.getAttribute('orientation'); 531 532 if (map.nodeName == "map") { 533 if (version != "1.0" && version !== null) 534 cc.log("cocos2d: TMXFormat: Unsupported TMX version:" + version); 535 536 if (orientationStr == "orthogonal") 537 this.orientation = cc.TMX_ORIENTATION_ORTHO; 538 else if (orientationStr == "isometric") 539 this.orientation = cc.TMX_ORIENTATION_ISO; 540 else if (orientationStr == "hexagonal") 541 this.orientation = cc.TMX_ORIENTATION_HEX; 542 else if (orientationStr !== null) 543 cc.log("cocos2d: TMXFomat: Unsupported orientation:" + orientationStr); 544 545 var mapSize = cc.size(0, 0); 546 mapSize.width = parseFloat(map.getAttribute('width')); 547 mapSize.height = parseFloat(map.getAttribute('height')); 548 this.setMapSize(mapSize); 549 550 mapSize = cc.size(0, 0); 551 mapSize.width = parseFloat(map.getAttribute('tilewidth')); 552 mapSize.height = parseFloat(map.getAttribute('tileheight')); 553 this.setTileSize(mapSize); 554 555 // The parent element is the map 556 var propertyArr = map.querySelectorAll("map > properties > property"); 557 if (propertyArr) { 558 var aPropertyDict = {}; 559 for (i = 0; i < propertyArr.length; i++) { 560 aPropertyDict[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value'); 561 } 562 this.properties = aPropertyDict; 563 } 564 } 565 566 // PARSE <tileset> 567 var tilesets = map.getElementsByTagName('tileset'); 568 if (map.nodeName !== "map") { 569 tilesets = []; 570 tilesets.push(map); 571 } 572 573 for (i = 0; i < tilesets.length; i++) { 574 var selTileset = tilesets[i]; 575 // If this is an external tileset then start parsing that 576 var tsxName = selTileset.getAttribute('source'); 577 if (tsxName) { 578 //this._currentFirstGID = parseInt(selTileset.getAttribute('firstgid')); 579 var tsxPath = isXmlString ? cc.path.join(this._resources, tsxName) : cc.path.changeBasename(tmxFile, tsxName); 580 this.parseXMLFile(tsxPath); 581 } else { 582 var tileset = new cc.TMXTilesetInfo(); 583 tileset.name = selTileset.getAttribute('name') || ""; 584 //TODO need fix 585 //if(this._currentFirstGID === 0){ 586 tileset.firstGid = parseInt(selTileset.getAttribute('firstgid')) || 0; 587 //}else{ 588 // tileset.firstGid = this._currentFirstGID; 589 // this._currentFirstGID = 0; 590 //} 591 592 tileset.spacing = parseInt(selTileset.getAttribute('spacing')) || 0; 593 tileset.margin = parseInt(selTileset.getAttribute('margin')) || 0; 594 595 var tilesetSize = cc.size(0, 0); 596 tilesetSize.width = parseFloat(selTileset.getAttribute('tilewidth')); 597 tilesetSize.height = parseFloat(selTileset.getAttribute('tileheight')); 598 tileset._tileSize = tilesetSize; 599 600 var image = selTileset.getElementsByTagName('image')[0]; 601 var imagename = image.getAttribute('source'); 602 var num = -1; 603 if(this.tmxFileName) 604 num = this.tmxFileName.lastIndexOf("/"); 605 if (num !== -1) { 606 var dir = this.tmxFileName.substr(0, num + 1); 607 tileset.sourceImage = dir + imagename; 608 } else { 609 tileset.sourceImage = this._resources + (this._resources ? "/" : "") + imagename; 610 } 611 this.setTilesets(tileset); 612 613 // PARSE <tile> 614 var tiles = selTileset.getElementsByTagName('tile'); 615 if (tiles) { 616 for (var tIdx = 0; tIdx < tiles.length; tIdx++) { 617 var t = tiles[tIdx]; 618 this.parentGID = parseInt(tileset.firstGid) + parseInt(t.getAttribute('id') || 0); 619 var tp = t.querySelectorAll("properties > property"); 620 if (tp) { 621 var dict = {}; 622 for (j = 0; j < tp.length; j++) { 623 var name = tp[j].getAttribute('name'); 624 dict[name] = tp[j].getAttribute('value'); 625 } 626 this._tileProperties[this.parentGID] = dict; 627 } 628 } 629 } 630 } 631 } 632 633 // PARSE <layer> 634 var layers = map.getElementsByTagName('layer'); 635 if (layers) { 636 for (i = 0; i < layers.length; i++) { 637 var selLayer = layers[i]; 638 var data = selLayer.getElementsByTagName('data')[0]; 639 640 var layer = new cc.TMXLayerInfo(); 641 layer.name = selLayer.getAttribute('name'); 642 643 var layerSize = cc.size(0, 0); 644 layerSize.width = parseFloat(selLayer.getAttribute('width')); 645 layerSize.height = parseFloat(selLayer.getAttribute('height')); 646 layer._layerSize = layerSize; 647 648 var visible = selLayer.getAttribute('visible'); 649 layer.visible = !(visible == "0"); 650 651 var opacity = selLayer.getAttribute('opacity') || 1; 652 653 if (opacity) 654 layer._opacity = parseInt(255 * parseFloat(opacity)); 655 else 656 layer._opacity = 255; 657 layer.offset = cc.p(parseFloat(selLayer.getAttribute('x')) || 0, parseFloat(selLayer.getAttribute('y')) || 0); 658 659 var nodeValue = ''; 660 for (j = 0; j < data.childNodes.length; j++) { 661 nodeValue += data.childNodes[j].nodeValue 662 } 663 nodeValue = nodeValue.trim(); 664 665 // Unpack the tilemap data 666 var compression = data.getAttribute('compression'); 667 var encoding = data.getAttribute('encoding'); 668 if(compression && compression !== "gzip" && compression !== "zlib"){ 669 cc.log("cc.TMXMapInfo.parseXMLFile(): unsupported compression method"); 670 return null; 671 } 672 switch (compression) { 673 case 'gzip': 674 layer._tiles = cc.unzipBase64AsArray(nodeValue, 4); 675 break; 676 case 'zlib': 677 var inflator = new Zlib.Inflate(cc.Codec.Base64.decodeAsArray(nodeValue, 1)); 678 layer._tiles = cc.uint8ArrayToUint32Array(inflator.decompress()); 679 break; 680 case null: 681 case '': 682 // Uncompressed 683 if (encoding == "base64") 684 layer._tiles = cc.Codec.Base64.decodeAsArray(nodeValue, 4); 685 else if (encoding === "csv") { 686 layer._tiles = []; 687 var csvTiles = nodeValue.split(','); 688 for (var csvIdx = 0; csvIdx < csvTiles.length; csvIdx++) 689 layer._tiles.push(parseInt(csvTiles[csvIdx])); 690 } else { 691 //XML format 692 var selDataTiles = data.getElementsByTagName("tile"); 693 layer._tiles = []; 694 for (var xmlIdx = 0; xmlIdx < selDataTiles.length; xmlIdx++) 695 layer._tiles.push(parseInt(selDataTiles[xmlIdx].getAttribute("gid"))); 696 } 697 break; 698 default: 699 if(this.layerAttrs == cc.TMXLayerInfo.ATTRIB_NONE) 700 cc.log("cc.TMXMapInfo.parseXMLFile(): Only base64 and/or gzip/zlib maps are supported"); 701 break; 702 } 703 704 // The parent element is the last layer 705 var layerProps = selLayer.querySelectorAll("properties > property"); 706 if (layerProps) { 707 var layerProp = {}; 708 for (j = 0; j < layerProps.length; j++) { 709 layerProp[layerProps[j].getAttribute('name')] = layerProps[j].getAttribute('value'); 710 } 711 layer.properties = layerProp; 712 } 713 this.setLayers(layer); 714 } 715 } 716 717 // PARSE <objectgroup> 718 var objectGroups = map.getElementsByTagName('objectgroup'); 719 if (objectGroups) { 720 for (i = 0; i < objectGroups.length; i++) { 721 var selGroup = objectGroups[i]; 722 var objectGroup = new cc.TMXObjectGroup(); 723 objectGroup.groupName = selGroup.getAttribute('name'); 724 objectGroup.setPositionOffset(cc.p(parseFloat(selGroup.getAttribute('x')) * this.getTileSize().width || 0, 725 parseFloat(selGroup.getAttribute('y')) * this.getTileSize().height || 0)); 726 727 var groupProps = selGroup.querySelectorAll("objectgroup > properties > property"); 728 if (groupProps) { 729 for (j = 0; j < groupProps.length; j++) { 730 var groupProp = {}; 731 groupProp[groupProps[j].getAttribute('name')] = groupProps[j].getAttribute('value'); 732 // Add the property to the layer 733 objectGroup.properties = groupProp; 734 } 735 } 736 737 var objects = selGroup.querySelectorAll('object'); 738 if (objects) { 739 for (j = 0; j < objects.length; j++) { 740 var selObj = objects[j]; 741 // The value for "type" was blank or not a valid class name 742 // Create an instance of TMXObjectInfo to store the object and its properties 743 var objectProp = {}; 744 745 // Set the name of the object to the value for "name" 746 objectProp["name"] = selObj.getAttribute('name') || ""; 747 748 // Assign all the attributes as key/name pairs in the properties dictionary 749 objectProp["type"] = selObj.getAttribute('type') || ""; 750 751 objectProp["x"] = parseInt(selObj.getAttribute('x') || 0) + objectGroup.getPositionOffset().x; 752 var y = parseInt(selObj.getAttribute('y') || 0) + objectGroup.getPositionOffset().y; 753 754 objectProp["width"] = parseInt(selObj.getAttribute('width')) || 0; 755 objectProp["height"] = parseInt(selObj.getAttribute('height')) || 0; 756 757 // Correct y position. (Tiled uses Flipped, cocos2d uses Standard) 758 objectProp["y"] = parseInt(this.getMapSize().height * this.getTileSize().height) - y - objectProp["height"]; 759 760 var docObjProps = selObj.querySelectorAll("properties > property"); 761 if (docObjProps) { 762 for (var k = 0; k < docObjProps.length; k++) 763 objectProp[docObjProps[k].getAttribute('name')] = docObjProps[k].getAttribute('value'); 764 } 765 766 //polygon 767 var polygonProps = selObj.querySelectorAll("polygon"); 768 if(polygonProps && polygonProps.length > 0) { 769 var selPgPointStr = polygonProps[0].getAttribute('points'); 770 if(selPgPointStr) 771 objectProp["polygonPoints"] = this._parsePointsString(selPgPointStr); 772 } 773 774 //polyline 775 var polylineProps = selObj.querySelectorAll("polyline"); 776 if(polylineProps && polylineProps.length > 0) { 777 var selPlPointStr = polylineProps[0].getAttribute('points'); 778 if(selPlPointStr) 779 objectProp["polylinePoints"] = this._parsePointsString(selPlPointStr); 780 } 781 782 // Add the object to the objectGroup 783 objectGroup.setObjects(objectProp); 784 } 785 } 786 787 this.setObjectGroups(objectGroup); 788 } 789 } 790 return map; 791 }, 792 793 _parsePointsString:function(pointsString){ 794 if(!pointsString) 795 return null; 796 797 var points = []; 798 var pointsStr = pointsString.split(' '); 799 for(var i = 0; i < pointsStr.length; i++){ 800 var selPointStr = pointsStr[i].split(','); 801 points.push({'x':selPointStr[0], 'y':selPointStr[1]}); 802 } 803 return points; 804 }, 805 806 /** 807 * initializes parsing of an XML string, either a tmx (Map) string or tsx (Tileset) string 808 * @param {String} xmlString 809 * @return {Boolean} 810 */ 811 parseXMLString:function (xmlString) { 812 return this.parseXMLFile(xmlString, true); 813 }, 814 815 /** 816 * @return {object} 817 */ 818 getTileProperties:function () { 819 return this._tileProperties; 820 }, 821 822 /** 823 * @param {object} tileProperties 824 */ 825 setTileProperties:function (tileProperties) { 826 this._tileProperties.push(tileProperties); 827 }, 828 829 /** 830 * @return {String} 831 */ 832 getCurrentString:function () { 833 return this.currentString; 834 }, 835 836 /** 837 * @param {String} currentString 838 */ 839 setCurrentString:function (currentString) { 840 this.currentString = currentString; 841 }, 842 843 /** 844 * @return {String} 845 */ 846 getTMXFileName:function () { 847 return this.tmxFileName; 848 }, 849 850 /** 851 * @param {String} fileName 852 */ 853 setTMXFileName:function (fileName) { 854 this.tmxFileName = fileName; 855 }, 856 857 _internalInit:function (tmxFileName, resourcePath) { 858 this._tilesets.length = 0; 859 this._layers.length = 0; 860 861 this.tmxFileName = tmxFileName; 862 if (resourcePath) 863 this._resources = resourcePath; 864 865 this._objectGroups.length = 0; 866 this.properties.length = 0; 867 this._tileProperties.length = 0; 868 869 // tmp vars 870 this.currentString = ""; 871 this.storingCharacters = false; 872 this.layerAttrs = cc.TMXLayerInfo.ATTRIB_NONE; 873 this.parentElement = cc.TMX_PROPERTY_NONE; 874 this._currentFirstGID = 0; 875 } 876 }); 877 878 var _p = cc.TMXMapInfo.prototype; 879 880 // Extended properties 881 /** @expose */ 882 _p.mapWidth; 883 cc.defineGetterSetter(_p, "mapWidth", _p._getMapWidth, _p._setMapWidth); 884 /** @expose */ 885 _p.mapHeight; 886 cc.defineGetterSetter(_p, "mapHeight", _p._getMapHeight, _p._setMapHeight); 887 /** @expose */ 888 _p.tileWidth; 889 cc.defineGetterSetter(_p, "tileWidth", _p._getTileWidth, _p._setTileWidth); 890 /** @expose */ 891 _p.tileHeight; 892 cc.defineGetterSetter(_p, "tileHeight", _p._getTileHeight, _p._setTileHeight); 893 894 895 /** 896 * Creates a TMX Format with a tmx file or content string 897 * @param {String} tmxFile fileName or content string 898 * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required. 899 * @return {cc.TMXMapInfo} 900 * @example 901 * 1. 902 * //create a TMXMapInfo with file name 903 * var tmxMapInfo = cc.TMXMapInfo.create("res/orthogonal-test1.tmx"); 904 * 2. 905 * //create a TMXMapInfo with content string and resource path 906 * var resources = "res/TileMaps"; 907 * var filePath = "res/TileMaps/orthogonal-test1.tmx"; 908 * var xmlStr = cc.loader.getRes(filePath); 909 * var tmxMapInfo = cc.TMXMapInfo.create(xmlStr, resources); 910 */ 911 cc.TMXMapInfo.create = function (tmxFile, resourcePath) { 912 return new cc.TMXMapInfo(tmxFile, resourcePath); 913 }; 914 915 916 cc.loader.register(["tmx", "tsx"], cc._txtLoader); 917 918 919 /** 920 * @constant 921 * @type Number 922 */ 923 cc.TMXLayerInfo.ATTRIB_NONE = 1 << 0; 924 /** 925 * @constant 926 * @type Number 927 */ 928 cc.TMXLayerInfo.ATTRIB_BASE64 = 1 << 1; 929 /** 930 * @constant 931 * @type Number 932 */ 933 cc.TMXLayerInfo.ATTRIB_GZIP = 1 << 2; 934 /** 935 * @constant 936 * @type Number 937 */ 938 cc.TMXLayerInfo.ATTRIB_ZLIB = 1 << 3; 939