Exemplo n.º 1
0
    def startElement(self, name, attributes):
        """
            This method processes the start of the XML elements
            In this method the following startelements will be processed:
                object
                objectgroup
                map
                tileset
                image
                tile
                property
                layer
        """

        #new object started
        if name == "object":
            self._currentObjectGroup.addObject(
                TmxObject(attributes['name'],
                    attributes['type'],
                    pygame.Rect(int(attributes['x']),
                        int(attributes['y']),
                        int(attributes['width']),
                        int(attributes['height']))
                    ))

        # objectgroup started
        elif name == "objectgroup":
            self._currentObjectGroup = TmxObjectGroup(
                attributes['name'], int(attributes['width']),
                int(attributes['height']))

        # new tilemap started
        elif name == "map":
            self.tileMap = TmxMap(attributes['version'],
                attributes['orientation'], int(attributes['width']),
                int(attributes['height']), int(attributes['tilewidth']),
                int(attributes['tileheight']))

        # new tileset started
        elif name == "tileset":
            if 'spacing' in attributes:
                tsSpacing = attributes['spacing']
            else:
                tsSpacing = 0

            if 'margin' in attributes:
                tsMargin = attributes['margin']
            else:
                tsMargin = 0
            self._currentTileset = TmxTileset(attributes['name'],
                int(attributes['tilewidth']), int(attributes['tileheight']),
                int(attributes['firstgid']),
                int(tsSpacing),
                int(tsMargin))
            self._currentBlock = "tileset"

        # image tag for tileset
        elif name == "image":
            if (self._currentTileset is not None):
                self._currentTileset.setImage(
                    pygame.image.load(
                    GameUtils.formatPath(attributes['source'], CFG_IMGSDIR)),
                    int(attributes['width']), int(attributes['height']))

        # tile/layer - tile properties
        elif name == "tile":
            if self._currentBlock == "tileset":
                self._currentGid = int(attributes['id'])
            if self._currentBlock == "layer":
                self._currentLayer.addTile(self._currentTileCount,
                    int(attributes['gid']),
                    self.tileMap.getTilesetByGid(int(attributes['gid'])))
                self._currentTileCount += 1

        # tile/layer property
        elif name == "property":
            if self._currentBlock == "tileset":
                # BUG: it is not the tileset's property. It is the
                # tile's property
                self._currentTileset.addTileProperty(self._currentGid,
                    attributes['name'],
                    attributes['value'])
            elif self._currentBlock == "layer":
                self._currentLayer.addProperty(attributes['name'],
                    attributes['value'])
        # new layer started
        elif name == "layer":
            self._currentLayer = TmxLayer(attributes['name'],
            int(attributes['width']), int(attributes['height'])
            )
            self._currentTileCount = 0
            self._currentBlock = "layer"
Exemplo n.º 2
0
class TmxFile(xml.sax.handler.ContentHandler):
    """
        This class loads a TMX MAP file into the memory from an
        exported TMX XML.

        You can export TMX file to XML using the
        TILED map editor: http://www.mapeditor.org/

        To export a TMX to XML do the followings:
            - Goto: Edit-->Preferences
            - Set "Store layer data as:" to XML
            - Goto: File-->Export as (ctrl+e)
            - Choose a filename and SAVE

        I used the xml.sax to parse the XML data.
        See: http://docs.python.org/2/library/xml.sax.html

        UPDATE-2013/02/13: At the end of the loading process, the program
        copies all tile properties to the layers' tiles, so the tileset's
        tileProperties only will contain the default values for the tiles,
        at runtime you should use the tmxTile.getTilePropertyValue(...).
    """

    tileMap = None              # tilemap to store data from XML
    _currentLayout = None       # current TMX layer
    _currentTileset = None      # current Tileset
    _loaded = False             # flag to mark the end of the loading
    _currentGid = 0             # to store the current gid for the tile
    _currentGidProperties = {}  # the properties of the current gid
    _currentBlock = ""          # the XML block which is currently processing
    _currentTileCount = 0       # the current tile's count
    _currentObjectGroup = None  # current object group

    def __init__(self):
        """
            Set up some initial value
        """
        self._loaded = False

    def isLoaded(self):
        """
            Returns True when the class finished the TMX processing.
            (When the file loaded.)
        """
        return self._loaded

    def startElement(self, name, attributes):
        """
            This method processes the start of the XML elements
            In this method the following startelements will be processed:
                object
                objectgroup
                map
                tileset
                image
                tile
                property
                layer
        """

        #new object started
        if name == "object":
            self._currentObjectGroup.addObject(
                TmxObject(attributes['name'],
                    attributes['type'],
                    pygame.Rect(int(attributes['x']),
                        int(attributes['y']),
                        int(attributes['width']),
                        int(attributes['height']))
                    ))

        # objectgroup started
        elif name == "objectgroup":
            self._currentObjectGroup = TmxObjectGroup(
                attributes['name'], int(attributes['width']),
                int(attributes['height']))

        # new tilemap started
        elif name == "map":
            self.tileMap = TmxMap(attributes['version'],
                attributes['orientation'], int(attributes['width']),
                int(attributes['height']), int(attributes['tilewidth']),
                int(attributes['tileheight']))

        # new tileset started
        elif name == "tileset":
            if 'spacing' in attributes:
                tsSpacing = attributes['spacing']
            else:
                tsSpacing = 0

            if 'margin' in attributes:
                tsMargin = attributes['margin']
            else:
                tsMargin = 0
            self._currentTileset = TmxTileset(attributes['name'],
                int(attributes['tilewidth']), int(attributes['tileheight']),
                int(attributes['firstgid']),
                int(tsSpacing),
                int(tsMargin))
            self._currentBlock = "tileset"

        # image tag for tileset
        elif name == "image":
            if (self._currentTileset is not None):
                self._currentTileset.setImage(
                    pygame.image.load(
                    GameUtils.formatPath(attributes['source'], CFG_IMGSDIR)),
                    int(attributes['width']), int(attributes['height']))

        # tile/layer - tile properties
        elif name == "tile":
            if self._currentBlock == "tileset":
                self._currentGid = int(attributes['id'])
            if self._currentBlock == "layer":
                self._currentLayer.addTile(self._currentTileCount,
                    int(attributes['gid']),
                    self.tileMap.getTilesetByGid(int(attributes['gid'])))
                self._currentTileCount += 1

        # tile/layer property
        elif name == "property":
            if self._currentBlock == "tileset":
                # BUG: it is not the tileset's property. It is the
                # tile's property
                self._currentTileset.addTileProperty(self._currentGid,
                    attributes['name'],
                    attributes['value'])
            elif self._currentBlock == "layer":
                self._currentLayer.addProperty(attributes['name'],
                    attributes['value'])
        # new layer started
        elif name == "layer":
            self._currentLayer = TmxLayer(attributes['name'],
            int(attributes['width']), int(attributes['height'])
            )
            self._currentTileCount = 0
            self._currentBlock = "layer"

    def characters(self, data):
        """
            Not used.
        """
        pass

    def endElement(self, name):
        """
            This method processes the endelements in the XML.
            The following endelements will be processed:
                objectgroup
                tileset
                layer
        """
        if name == "objectgroup":
            # objectgroup's end, add it to objectgroups
            self.tileMap.addObjectGroup(self._currentObjectGroup)
            del self._currentObjectGroup

        elif name == "tileset":
            # tileset's end, add it to the tilesets
            self.tileMap.addTileset(self._currentTileset)
            del self._currentTileset

        elif name == "layer":
            # layer's end, add it to the layers
            self.tileMap.addLayer(self._currentLayer)
            del self._currentLayer

    def loadTmx(self, filename):
        """
            This method starts the TMX loading.
            You need to specify the filename and when it finishes the process
            the isLoaded() method will return True.
        """
        self._loaded = False
        parser = xml.sax.make_parser()
        parser.setContentHandler(self)
        # DO NOT USE DTD reference in "Tiled", because
        # without a http connection, it can ruin the loading
        # process
        parser.parse(filename)
        self._loaded = True
        return self.tileMap