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