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