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 ctor:function () { 288 cc.SAXParser.prototype.ctor.apply(this); 289 this._mapSize = cc.size(0, 0); 290 this._tileSize = cc.size(0, 0); 291 this._layers = []; 292 this._tilesets = []; 293 this._objectGroups = []; 294 this.properties = []; 295 this._tileProperties = {}; 296 297 this._currentFirstGID = 0; 298 }, 299 /** 300 * @return {Number} 301 */ 302 getOrientation:function () { 303 return this.orientation; 304 }, 305 306 /** 307 * @param {Number} value 308 */ 309 setOrientation:function (value) { 310 this.orientation = value; 311 }, 312 313 /** 314 * Map width & height 315 * @return {cc.Size} 316 */ 317 getMapSize:function () { 318 return cc.size(this._mapSize.width,this._mapSize.height); 319 }, 320 321 /** 322 * @param {cc.Size} value 323 */ 324 setMapSize:function (value) { 325 this._mapSize.width = value.width; 326 this._mapSize.height = value.height; 327 }, 328 329 _getMapWidth: function () { 330 return this._mapSize.width; 331 }, 332 _setMapWidth: function (width) { 333 this._mapSize.width = width; 334 }, 335 _getMapHeight: function () { 336 return this._mapSize.height; 337 }, 338 _setMapHeight: function (height) { 339 this._mapSize.height = height; 340 }, 341 342 /** 343 * Tiles width & height 344 * @return {cc.Size} 345 */ 346 getTileSize:function () { 347 return cc.size(this._tileSize.width, this._tileSize.height); 348 }, 349 350 /** 351 * @param {cc.Size} value 352 */ 353 setTileSize:function (value) { 354 this._tileSize.width = value.width; 355 this._tileSize.height = value.height; 356 }, 357 358 _getTileWidth: function () { 359 return this._tileSize.width; 360 }, 361 _setTileWidth: function (width) { 362 this._tileSize.width = width; 363 }, 364 _getTileHeight: function () { 365 return this._tileSize.height; 366 }, 367 _setTileHeight: function (height) { 368 this._tileSize.height = height; 369 }, 370 371 /** 372 * Layers 373 * @return {Array} 374 */ 375 getLayers:function () { 376 return this._layers; 377 }, 378 379 /** 380 * @param {cc.TMXLayerInfo} value 381 */ 382 setLayers:function (value) { 383 this._layers.push(value); 384 }, 385 386 /** 387 * tilesets 388 * @return {Array} 389 */ 390 getTilesets:function () { 391 return this._tilesets; 392 }, 393 394 /** 395 * @param {cc.TMXTilesetInfo} value 396 */ 397 setTilesets:function (value) { 398 this._tilesets.push(value); 399 }, 400 401 /** 402 * ObjectGroups 403 * @return {Array} 404 */ 405 getObjectGroups:function () { 406 return this._objectGroups; 407 }, 408 409 /** 410 * @param {cc.TMXObjectGroup} value 411 */ 412 setObjectGroups:function (value) { 413 this._objectGroups.push(value); 414 }, 415 416 /** 417 * parent element 418 * @return {Object} 419 */ 420 getParentElement:function () { 421 return this.parentElement; 422 }, 423 424 /** 425 * @param {Object} value 426 */ 427 setParentElement:function (value) { 428 this.parentElement = value; 429 }, 430 431 /** 432 * parent GID 433 * @return {Number} 434 */ 435 getParentGID:function () { 436 return this.parentGID; 437 }, 438 439 /** 440 * @param {Number} value 441 */ 442 setParentGID:function (value) { 443 this.parentGID = value; 444 }, 445 446 /** 447 * Layer attribute 448 * @return {Object} 449 */ 450 getLayerAttribs:function () { 451 return this.layerAttrs; 452 }, 453 454 /** 455 * @param {Object} value 456 */ 457 setLayerAttribs:function (value) { 458 this.layerAttrs = value; 459 }, 460 461 /** 462 * Is reading storing characters stream 463 * @return {Boolean} 464 */ 465 getStoringCharacters:function () { 466 return this.storingCharacters; 467 }, 468 469 /** 470 * @param {Boolean} value 471 */ 472 setStoringCharacters:function (value) { 473 this.storingCharacters = value; 474 }, 475 476 /** 477 * Properties 478 * @return {Array} 479 */ 480 getProperties:function () { 481 return this.properties; 482 }, 483 484 /** 485 * @param {object} value 486 */ 487 setProperties:function (value) { 488 this.properties = value; 489 }, 490 491 /** 492 * Initializes a TMX format with a tmx file 493 * @param {String} tmxFile 494 * @return {Element} 495 */ 496 initWithTMXFile:function (tmxFile) { 497 this._internalInit(tmxFile, null); 498 return this.parseXMLFile(tmxFile); 499 }, 500 501 /** 502 * initializes a TMX format with an XML string and a TMX resource path 503 * @param {String} tmxString 504 * @param {String} resourcePath 505 * @return {Boolean} 506 */ 507 initWithXML:function (tmxString, resourcePath) { 508 this._internalInit(null, resourcePath); 509 return this.parseXMLString(tmxString); 510 }, 511 512 /** Initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file 513 * @param {String} tmxFile 514 * @param {boolean} [isXmlString=false] 515 * @return {Element} 516 */ 517 parseXMLFile:function (tmxFile, isXmlString) { 518 isXmlString = isXmlString || false; 519 var xmlStr = isXmlString ? tmxFile : cc.loader.getRes(tmxFile); 520 if(!xmlStr) throw "Please load the resource first : " + tmxFile; 521 522 var mapXML = this._parseXML(xmlStr); 523 var i, j; 524 525 // PARSE <map> 526 var map = mapXML.documentElement; 527 528 var version = map.getAttribute('version'); 529 var orientationStr = map.getAttribute('orientation'); 530 531 if (map.nodeName == "map") { 532 if (version != "1.0" && version !== null) 533 cc.log("cocos2d: TMXFormat: Unsupported TMX version:" + version); 534 535 if (orientationStr == "orthogonal") 536 this.orientation = cc.TMX_ORIENTATION_ORTHO; 537 else if (orientationStr == "isometric") 538 this.orientation = cc.TMX_ORIENTATION_ISO; 539 else if (orientationStr == "hexagonal") 540 this.orientation = cc.TMX_ORIENTATION_HEX; 541 else if (orientationStr !== null) 542 cc.log("cocos2d: TMXFomat: Unsupported orientation:" + orientationStr); 543 544 var mapSize = cc.size(0, 0); 545 mapSize.width = parseFloat(map.getAttribute('width')); 546 mapSize.height = parseFloat(map.getAttribute('height')); 547 this.setMapSize(mapSize); 548 549 mapSize = cc.size(0, 0); 550 mapSize.width = parseFloat(map.getAttribute('tilewidth')); 551 mapSize.height = parseFloat(map.getAttribute('tileheight')); 552 this.setTileSize(mapSize); 553 554 // The parent element is the map 555 var propertyArr = map.querySelectorAll("map > properties > property"); 556 if (propertyArr) { 557 var aPropertyDict = {}; 558 for (i = 0; i < propertyArr.length; i++) { 559 aPropertyDict[propertyArr[i].getAttribute('name')] = propertyArr[i].getAttribute('value'); 560 } 561 this.properties = aPropertyDict; 562 } 563 } 564 565 // PARSE <tileset> 566 var tilesets = map.getElementsByTagName('tileset'); 567 if (map.nodeName !== "map") { 568 tilesets = []; 569 tilesets.push(map); 570 } 571 572 for (i = 0; i < tilesets.length; i++) { 573 var selTileset = tilesets[i]; 574 // If this is an external tileset then start parsing that 575 var tsxName = selTileset.getAttribute('source'); 576 if (tsxName) { 577 //this._currentFirstGID = parseInt(selTileset.getAttribute('firstgid')); 578 var tsxPath = isXmlString ? cc.path.join(this._resources, tsxName) : cc.path.changeBasename(tmxFile, tsxName); 579 this.parseXMLFile(tsxPath); 580 } else { 581 var tileset = new cc.TMXTilesetInfo(); 582 tileset.name = selTileset.getAttribute('name') || ""; 583 //TODO need fix 584 //if(this._currentFirstGID === 0){ 585 tileset.firstGid = parseInt(selTileset.getAttribute('firstgid')) || 0; 586 //}else{ 587 // tileset.firstGid = this._currentFirstGID; 588 // this._currentFirstGID = 0; 589 //} 590 591 tileset.spacing = parseInt(selTileset.getAttribute('spacing')) || 0; 592 tileset.margin = parseInt(selTileset.getAttribute('margin')) || 0; 593 594 var tilesetSize = cc.size(0, 0); 595 tilesetSize.width = parseFloat(selTileset.getAttribute('tilewidth')); 596 tilesetSize.height = parseFloat(selTileset.getAttribute('tileheight')); 597 tileset._tileSize = tilesetSize; 598 599 var image = selTileset.getElementsByTagName('image')[0]; 600 var imagename = image.getAttribute('source'); 601 var num = -1; 602 if(this.tmxFileName) 603 num = this.tmxFileName.lastIndexOf("/"); 604 if (num !== -1) { 605 var dir = this.tmxFileName.substr(0, num + 1); 606 tileset.sourceImage = dir + imagename; 607 } else { 608 tileset.sourceImage = this._resources + (this._resources ? "/" : "") + imagename; 609 } 610 this.setTilesets(tileset); 611 } 612 } 613 614 // PARSE <tile> 615 var tiles = map.querySelectorAll('tile'); 616 if (tiles) { 617 for (i = 0; i < tiles.length; i++) { 618 var info = this._tilesets[0]; 619 var t = tiles[i]; 620 this.parentGID = parseInt(info.firstGid) + parseInt(t.getAttribute('id') || 0); 621 var tp = t.querySelectorAll("properties > property"); 622 if (tp) { 623 var dict = {}; 624 for (j = 0; j < tp.length; j++) { 625 var name = tp[j].getAttribute('name'); 626 dict[name] = tp[j].getAttribute('value'); 627 } 628 this._tileProperties[this.parentGID] = dict; 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.TMX_LAYER_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.TMX_LAYER_ATTRIB_NONE; 873 this.parentElement = cc.TMX_PROPERTY_NONE; 874 this._currentFirstGID = 0; 875 } 876 }); 877 878 window._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 delete window._p; 895 896 /** 897 * Creates a TMX Format with a tmx file or content string 898 * @param {String} tmxFile fileName or content string 899 * @param {String} resourcePath If tmxFile is a file name ,it is not required.If tmxFile is content string ,it is must required. 900 * @return {cc.TMXMapInfo} 901 * @example 902 * 1. 903 * //create a TMXMapInfo with file name 904 * var tmxMapInfo = cc.TMXMapInfo.create("res/orthogonal-test1.tmx"); 905 * 2. 906 * //create a TMXMapInfo with content string and resource path 907 * var resources = "res/TileMaps"; 908 * var filePath = "res/TileMaps/orthogonal-test1.tmx"; 909 * var xmlStr = cc.loader.getRes(filePath); 910 * var tmxMapInfo = cc.TMXMapInfo.create(xmlStr, resources); 911 */ 912 cc.TMXMapInfo.create = function (tmxFile, resourcePath) { 913 var ret = new cc.TMXMapInfo(); 914 if (resourcePath) { 915 if (ret.initWithXML(tmxFile, resourcePath)) 916 return ret; 917 } else { 918 if (ret.initWithTMXFile(tmxFile)) 919 return ret; 920 } 921 return null; 922 }; 923 924 925 cc.loader.register(["tmx", "tsx"], cc._txtLoader); 926