Permalink
Browse files

Allow loading TMX maps asynchronously

  • Loading branch information...
1 parent 98efc68 commit 5e00dc9079578876f7bf85b7e1855e8787f27948 @ryanwilliams committed Jun 10, 2012
Showing with 142 additions and 61 deletions.
  1. +29 −16 src/TMXXMLParser.js
  2. +11 −0 src/libs/uri.js
  3. +14 −6 src/nodes/BatchNode.js
  4. +4 −0 src/nodes/Node.js
  5. +22 −14 src/nodes/TMXLayer.js
  6. +62 −25 src/nodes/TMXTiledMap.js
View
45 src/TMXXMLParser.js
@@ -1,13 +1,14 @@
'use strict'
-var util = require('util'),
- path = require('path'),
- ccp = require('geometry').ccp,
- base64 = require('base64'),
- gzip = require('gzip'),
- TMXOrientationOrtho = require('./TMXOrientation').TMXOrientationOrtho,
- TMXOrientationHex = require('./TMXOrientation').TMXOrientationHex,
- TMXOrientationIso = require('./TMXOrientation').TMXOrientationIso
+var util = require('util')
+ , uri = require('uri')
+ , path = require('path')
+ , ccp = require('geometry').ccp
+ , base64 = require('base64')
+ , gzip = require('gzip')
+ , TMXOrientationOrtho = require('./TMXOrientation').TMXOrientationOrtho
+ , TMXOrientationHex = require('./TMXOrientation').TMXOrientationHex
+ , TMXOrientationIso = require('./TMXOrientation').TMXOrientationIso
/**
* @class
@@ -137,15 +138,15 @@ TMXObjectGroup.inherit(Object, /** @lends cocos.TMXObjectGroup# */ {
*
* @param {String} tmxFile The file path of the TMX file to load
*/
-function TMXMapInfo (tmxFile) {
+function TMXMapInfo (opts) {
this.tilesets = []
this.layers = []
this.objectGroups = []
this.properties = {}
this.tileProperties = {}
- this.filename = tmxFile
+ this.filename = opts.filename || opts.file || ''
- this.parseXMLFile(tmxFile)
+ this.parseXMLFile(opts)
}
TMXMapInfo.inherit(Object, /** @lends cocos.TMXMapInfo# */ {
@@ -159,9 +160,14 @@ TMXMapInfo.inherit(Object, /** @lends cocos.TMXMapInfo# */ {
properties: null,
tileProperties: null,
- parseXMLFile: function (xmlFile) {
- var parser = new DOMParser(),
- doc = parser.parseFromString(resource(xmlFile), 'text/xml')
+ parseXMLFile: function (opts) {
+ var parser = new DOMParser()
+ , doc
+
+ if (opts.file)
+ doc = parser.parseFromString(resource(opts.file), 'text/xml')
+ else if (opts.xml)
+ doc = parser.parseFromString(opts.xml, 'text/xml')
// PARSE <map>
var map = doc.documentElement
@@ -198,7 +204,8 @@ TMXMapInfo.inherit(Object, /** @lends cocos.TMXMapInfo# */ {
// happen AFTER 'firstGID' is obtained because firstGID is stored
// in the main .tmx file, not the .tsx
if (externalTilesetName) {
- var externalTilesetPath = path.join(path.dirname(xmlFile), externalTilesetName)
+ // FIXME needs to support opts.url too
+ var externalTilesetPath = path.join(path.dirname(opts.file), externalTilesetName)
t = parser.parseFromString(resource(externalTilesetPath), 'text/xml').documentElement
}
@@ -220,7 +227,13 @@ TMXMapInfo.inherit(Object, /** @lends cocos.TMXMapInfo# */ {
if (externalTilesetName) {
tileset.sourceImage = path.join(path.dirname(externalTilesetPath), image.getAttribute('source'))
} else {
- tileset.sourceImage = path.join(path.dirname(this.filename), image.getAttribute('source'))
+ // Check of URL or file path
+ if (uri.isURL(this.filename)) {
+ var base = path.dirname(this.filename)
+ tileset.sourceImage = path.dirname(this.filename) + '/' + image.getAttribute('source')
+ } else {
+ tileset.sourceImage = path.join(path.dirname(this.filename), image.getAttribute('source'))
+ }
}
this.tilesets.push(tileset)
View
11 src/libs/uri.js
@@ -0,0 +1,11 @@
+/**
+ * @namespace
+ * URI utilities
+ */
+var uri = {
+ isURL: function (uri) {
+ return /^(file|http|https):\/\//.test(uri)
+ }
+}
+
+module.exports = uri
View
20 src/nodes/BatchNode.js
@@ -219,12 +219,20 @@ BatchNode.inherit(Node, /** @lends cocos.nodes.BatchNode# */ {
function SpriteBatchNode (opts) {
SpriteBatchNode.superclass.constructor.call(this, opts)
- var file = opts.file,
- textureAtlas = opts.textureAtlas,
- texture = opts.texture
-
- if (file || texture) {
- textureAtlas = new TextureAtlas({file: file, texture: texture})
+ var file = opts.file
+ , url = opts.url
+ , textureAtlas = opts.textureAtlas
+ , texture = opts.texture
+
+ if (url || file || texture) {
+ this.ready = url ? false : true
+ textureAtlas = new TextureAtlas({url: url, file: file, texture: texture})
+
+ if (!this.ready) {
+ events.addListenerOnce(textureAtlas, 'load', function () {
+ this.ready = true
+ }.bind(this))
+ }
}
this.textureAtlas = textureAtlas
View
4 src/nodes/Node.js
@@ -43,6 +43,10 @@ Node.inherit(Object, /** @lends cocos.nodes.Node# */ {
, set position (x) { this._position = x; events.trigger(this, 'dirtytransform', {target: this, property: 'position'}) }
, _position: null
+ , get ready () { return this._ready }
+ , set ready (x) { this._ready = !!x; x && events.trigger(this, 'ready', {target: this}) }
+ , _ready: true
+
/**
* Parent node
* @type cocos.nodes.Node
View
36 src/nodes/TMXLayer.js
@@ -1,15 +1,16 @@
'use strict'
-var util = require('util'),
- events = require('events'),
- SpriteBatchNode = require('./BatchNode').SpriteBatchNode,
- Sprite = require('./Sprite').Sprite,
- TMXOrientationOrtho = require('../TMXOrientation').TMXOrientationOrtho,
- TMXOrientationHex = require('../TMXOrientation').TMXOrientationHex,
- TMXOrientationIso = require('../TMXOrientation').TMXOrientationIso,
- geo = require('geometry'),
- ccp = geo.ccp,
- Node = require('./Node').Node
+var util = require('util')
+ , uri = require('uri')
+ , events = require('events')
+ , SpriteBatchNode = require('./BatchNode').SpriteBatchNode
+ , Sprite = require('./Sprite').Sprite
+ , TMXOrientationOrtho = require('../TMXOrientation').TMXOrientationOrtho
+ , TMXOrientationHex = require('../TMXOrientation').TMXOrientationHex
+ , TMXOrientationIso = require('../TMXOrientation').TMXOrientationIso
+ , geo = require('geometry')
+ , ccp = geo.ccp
+ , Node = require('./Node').Node
@@ -41,7 +42,12 @@ function TMXLayer (opts) {
tex = tilesetInfo.sourceImage
}
- TMXLayer.superclass.constructor.call(this, {file: tex})
+ if (uri.isURL(tex)) {
+ TMXLayer.superclass.constructor.call(this, {url: tex})
+ } else {
+ TMXLayer.superclass.constructor.call(this, {file: tex})
+ }
+
this.anchorPoint = ccp(0, 0)
@@ -91,9 +97,11 @@ TMXLayer.inherit(SpriteBatchNode, /** @lends cocos.nodes.TMXLayer# */ {
},
setupTiles: function () {
- events.addPropertyListener(this.texture, 'contentSize', 'change', function (e) {
- this.tileset.imageSize = this.texture.contentSize
- }.bind(this))
+ if (!this.ready) {
+ events.addListenerOnce(this, 'ready', this.setupTiles.bind(this))
+ return
+ }
+
this.tileset.imageSize = this.texture.contentSize
this.parseInternalProperties()
View
87 src/nodes/TMXTiledMap.js
@@ -24,31 +24,65 @@ function TMXTiledMap (opts) {
this.anchorPoint = ccp(0, 0)
- var mapInfo = new TMXMapInfo(opts.file)
-
- this.mapSize = mapInfo.mapSize
- this.tileSize = mapInfo.tileSize
- this.mapOrientation = mapInfo.orientation
- this.objectGroups = mapInfo.objectGroups
- this.properties = mapInfo.properties
- this.tileProperties = mapInfo.tileProperties
-
- // Add layers to map
- var idx = 0
- mapInfo.layers.forEach(function (layerInfo) {
- if (layerInfo.visible) {
- var child = this.parseLayer({layerInfo: layerInfo, mapInfo: mapInfo})
- this.addChild({child: child, z: idx, tag: idx})
-
- var childSize = child.contentSize
- var currentSize = this.contentSize
- currentSize.width = Math.max(currentSize.width, childSize.width)
- currentSize.height = Math.max(currentSize.height, childSize.height)
- this.contentSize = currentSize
-
- idx++
+ var mapInfo
+
+ var initialize = function () {
+ this.mapSize = mapInfo.mapSize
+ this.tileSize = mapInfo.tileSize
+ this.mapOrientation = mapInfo.orientation
+ this.objectGroups = mapInfo.objectGroups
+ this.properties = mapInfo.properties
+ this.tileProperties = mapInfo.tileProperties
+
+ // Add layers to map
+ var idx = 0
+ mapInfo.layers.forEach(function (layerInfo) {
+ if (layerInfo.visible) {
+ var child = this.parseLayer({layerInfo: layerInfo, mapInfo: mapInfo})
+ this.addChild({child: child, z: idx, tag: idx})
+
+ var childSize = child.contentSize
+ var currentSize = this.contentSize
+ currentSize.width = Math.max(currentSize.width, childSize.width)
+ currentSize.height = Math.max(currentSize.height, childSize.height)
+ this.contentSize = currentSize
+
+ idx++
+ }
+ }.bind(this))
+ }.bind(this)
+
+
+ if (opts.file) {
+ mapInfo = new TMXMapInfo({file: opts.file})
+ initialize()
+ } else if (opts.url) {
+ var xhr = new XMLHttpRequest
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState == 4) {
+ var url = opts.url
+
+ // Create absolute URL
+ if (/^\/\//.test(url)) {
+ // URL prefixed with double slash
+ url = window.location.protocol + url
+ } else if (/^\//.test(url)) {
+ // URL with single slash prefix
+ url = window.location.protocol + "//" + window.location.hostname + url
+ } else {
+ url = window.location.href.replace(/\/[^\/]*$/, '/') + url
+ }
+
+ mapInfo = new TMXMapInfo({filename: url, xml: xhr.responseText})
+ initialize()
+ }
}
- }.bind(this))
+ xhr.open('GET', opts.url, true)
+ xhr.send(null)
+ } else if (opts.xml) {
+ mapInfo = new TMXMapInfo({xml: opts.xml})
+ initialize()
+ }
}
@@ -62,7 +96,10 @@ TMXTiledMap.inherit(Node, /** @lends cocos.nodes.TMXTiledMap# */ {
parseLayer: function (opts) {
var tileset = this.tilesetForLayer(opts)
- var layer = new TMXLayer({tilesetInfo: tileset, layerInfo: opts.layerInfo, mapInfo: opts.mapInfo})
+ var layer = new TMXLayer({ tilesetInfo: tileset
+ , layerInfo: opts.layerInfo
+ , mapInfo: opts.mapInfo
+ })
layer.setupTiles()

0 comments on commit 5e00dc9

Please sign in to comment.