├── .gitignore ├── LICENSE ├── README.md ├── as3-tiled-reader.iml ├── bin └── as3-tiled-reader.swc └── src └── io └── arkeus └── tiled ├── TiledImage.as ├── TiledImageLayer.as ├── TiledLayer.as ├── TiledLayers.as ├── TiledMap.as ├── TiledObject.as ├── TiledObjectLayer.as ├── TiledProperties.as ├── TiledReader.as ├── TiledTerrain.as ├── TiledTile.as ├── TiledTileLayer.as ├── TiledTileset.as ├── TiledTilesets.as ├── TiledUtils.as └── base64 └── Base64.as /.gitignore: -------------------------------------------------------------------------------- 1 | html-template 2 | bin-debug 3 | bin-release 4 | www 5 | air 6 | docs 7 | .settings 8 | .actionScriptProperties 9 | .project 10 | .git 11 | org 12 | adobe 13 | *.psd 14 | Thumbs.db 15 | .DS_Store 16 | .flexLibProperties -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Lee Miller 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AS3 Tiled Reader 2 | ==== 3 | 4 | About 5 | ----- 6 | 7 | Tiled Reader is an as3 tmx parser allowing you to read maps exported via the [Tiled Map Editor](http://www.mapeditor.org/ "Tiled Map Editor"). Tiled Reader was created to allow you to easily save your Tiled maps using the default format and load them in flash games. 8 | 9 | Features 10 | -------- 11 | 12 | Tiled Reader allows you to load maps that are compressed using zlib and encoded using base64. It takes advantage of the native flash zlib compression, and uses a very fast open source base64 library to decode your layer data. 13 | 14 | Tiled Reader supports all major features of Tiled 0.9.0, including tile layers, object layers, image layers, properties, and terrain. 15 | 16 | How To Use 17 | ---------- 18 | 19 | Using Tiled Reader is easy. You either either embed a TMX file directly into your application, or parse an XML object direct. 20 | 21 | If you choose to use an embedded file, embed the map as follows: 22 | 23 | [Embed(source = "/map/world.tmx", mimeType = "application/octet-stream")] public static const WORLD:Class; 24 | 25 | You can then load, and parse the map file as follows: 26 | 27 | var reader:TiledReader = new TiledReader; 28 | var map:TiledMap = reader.loadFromEmbedded(WORLD); 29 | 30 | If you want to use an actual XML object, load the XML using any method you'd like (internally or externally), and simple use the loadFromXML function on TiledReader. 31 | 32 | After loading the file, you can access layers, properties, and more from the returned TiledMap. Check out the TiledMap.as file's documentation for all attributes and functions. 33 | 34 | Example 35 | ------- 36 | 37 | To see an example of Tiled Reader being used, check out the [Axelite Moon](https://github.com/arkeus/axelite-moon "Axelite Moon") project. 38 | 39 | Support 40 | ------- 41 | 42 | If you find a bug, or notice that a feature isn't support, feel free to open an issue against the project! -------------------------------------------------------------------------------- /as3-tiled-reader.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /bin/as3-tiled-reader.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkeus/as3-tiled-reader/bba566c4619d5ca34c097d2850656af26243017d/bin/as3-tiled-reader.swc -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledImage.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * Represents an image within a tiled map. The source is a string containing the path 4 | * to the image relative to the location of the map. 5 | */ 6 | public class TiledImage { 7 | /** The string containing the path to the image relative to the map file. */ 8 | public var source:String; 9 | /** The width of the image. */ 10 | public var width:uint; 11 | /** The height of the image. */ 12 | public var height:uint; 13 | /** The transparent color, -1 if no transparent color. */ 14 | public var transparentColor:int; 15 | 16 | /** 17 | * @param tmx The XMLList containing the object. 18 | */ 19 | public function TiledImage(tmx:XMLList) { 20 | source = tmx.@source; 21 | width = tmx.@width; 22 | height = tmx.@height; 23 | transparentColor = "@trans" in tmx ? TiledUtils.colorStringToUint(tmx.@trans) : -1; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledImageLayer.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A class representing an layer. In addition to the base layer properties, 4 | * an image layer contains a single image. 5 | */ 6 | public class TiledImageLayer extends TiledLayer { 7 | /** The layer's image. */ 8 | public var image:TiledImage; 9 | 10 | /** 11 | * @param tmx The XML containing the object. 12 | */ 13 | public function TiledImageLayer(tmx:XML) { 14 | super(tmx); 15 | image = new TiledImage(tmx.image); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledLayer.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * Represents a layer in the map. Layers can be one of three types: TiledTileLayer (tile layer), 4 | * TiledImageLayer (image layer), or TiledObjectLayer (object group). 5 | */ 6 | public class TiledLayer { 7 | /** The name of the layer. */ 8 | public var name:String; 9 | /** The width of the layer. Usually equal to the map width. */ 10 | public var width:uint; 11 | /** The height of the layer. Usually equal to the map height. */ 12 | public var height:uint; 13 | /** The opacity of the map between 0.0 and 1.0. */ 14 | public var opacity:Number; 15 | /** Whether or not this layer is set to be visible or not. */ 16 | public var visible:Boolean; 17 | /** Layer properties. */ 18 | public var properties:TiledProperties; 19 | 20 | /** 21 | * @param tmx The XML containing the layer object. 22 | */ 23 | public function TiledLayer(tmx:XML) { 24 | name = tmx.@name; 25 | width = tmx.@width; 26 | height = tmx.@height; 27 | opacity = "@opacity" in tmx ? tmx.@opacity : 1.0; 28 | visible = !("@visible" in tmx && tmx.@visible == "0"); 29 | properties = new TiledProperties(tmx.properties); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledLayers.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A container holding all the layers within the map. Provides utility functions for grabbing 4 | * visible layers, tile layers, and all layers. 5 | */ 6 | /** 7 | * 8 | * @author Lee 9 | */ 10 | public class TiledLayers { 11 | /** The vector of layers in order from bottom to top. */ 12 | public var layers:Vector.; 13 | 14 | public function TiledLayers() { 15 | layers = new Vector.; 16 | } 17 | 18 | /** 19 | * Adds a layer on top of all other layers. 20 | * 21 | * @param layer The layer to add. 22 | */ 23 | public function addLayer(layer:TiledLayer):void { 24 | layers.push(layer); 25 | } 26 | 27 | /** 28 | * Returns a vector of all layers in order from bottom to top. 29 | * 30 | * @return The vector of all layers. 31 | */ 32 | public function getAllLayers():Vector. { 33 | return layers; 34 | } 35 | 36 | /** 37 | * Returns a vector of all visible layers in order from bottom to top. 38 | * 39 | * @return The vector of all visible layers. 40 | */ 41 | public function getVisibleLayers():Vector. { 42 | return layers.filter(function(el:TiledLayer, i:int, arr:Vector.):Boolean { return el.visible; }); 43 | } 44 | 45 | /** 46 | * Returns a vector of all tile layers in order from bottom to top. 47 | * 48 | * @return The vector of all tile layers. 49 | */ 50 | public function getTileLayers():Vector. { 51 | return layers.filter(function(el:TiledLayer, i:int, arr:Vector.):Boolean { return el is TiledTileLayer; }); 52 | } 53 | 54 | /** 55 | * Returns a vector of all object layers in order from bottom to top. 56 | * 57 | * @return The vector of all object layers. 58 | */ 59 | public function getObjectLayers():Vector. { 60 | return layers.filter(function(el:TiledLayer, i:int, arr:Vector.):Boolean { return el is TiledObjectLayer; }); 61 | } 62 | 63 | /** 64 | * Returns the number of layers in the map. 65 | * 66 | * @return The number of layers. 67 | */ 68 | public function get length():uint { 69 | return layers.length; 70 | } 71 | 72 | /** 73 | * Overwrites toString to simple return the number of layers. 74 | */ 75 | public function toString():String { 76 | return length + " layers"; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledMap.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A fully parsed tiled map. Contains all information about the map, including the 4 | * parsed layers. 5 | */ 6 | public class TiledMap { 7 | /** The TMX format version, always 1.0 currently. */ 8 | public var version:String; 9 | /** Map orientation, one of: orthogonal, isometric, stagerred. */ 10 | public var orientation:String; 11 | /** The width of the map in tiles. */ 12 | public var width:uint; 13 | /** The height of the map in tiles. */ 14 | public var height:uint; 15 | /** The width of a tile in pixels. */ 16 | public var tileWidth:uint; 17 | /** The height of a tile in pixels. */ 18 | public var tileHeight:uint; 19 | /** The background color of the map. */ 20 | public var backgroundColor:uint; 21 | /** Properties of the map. */ 22 | public var properties:TiledProperties; 23 | /** A container containing information on the tilesets of the map. */ 24 | public var tilesets:TiledTilesets; 25 | /** A container containing information on the layers of the map. */ 26 | public var layers:TiledLayers; 27 | 28 | public function TiledMap(tmx:XML) { 29 | version = "@version" in tmx ? tmx.@version : "?"; 30 | orientation = "@orientation" in tmx ? tmx.@orientation : "othogonal"; 31 | width = tmx.@width; 32 | height = tmx.@height; 33 | tileWidth = tmx.@tilewidth; 34 | tileHeight = tmx.@tileheight; 35 | backgroundColor = "@backgroundcolor" in tmx ? TiledUtils.colorStringToUint(tmx.@backgroundcolor) : 0xffffff; 36 | properties = new TiledProperties(tmx.properties); 37 | tilesets = new TiledTilesets(tmx.tileset); 38 | parseLayers(tmx); 39 | } 40 | 41 | /** 42 | * Parses the layers of the map, building the TiledLayers container containing information 43 | * on each parsed layer. The order of the layers is kept intact, from bottom to top. 44 | * 45 | * @param tmx The map object. 46 | */ 47 | private function parseLayers(tmx:XML):void { 48 | layers = new TiledLayers; 49 | 50 | // Parse all children, since for some reason layer and objectgroup aren't grouped easily, even though the ordering 51 | // between them can be very important. WHY BJORN, WHY? 52 | var elements:XMLList = tmx.children(); 53 | for (var i:uint = 0; i < elements.length(); i++) { 54 | var name:QName = (elements[i] as XML).name() as QName; 55 | if (name.localName == "layer") { 56 | layers.addLayer(new TiledTileLayer(elements[i])); 57 | } else if (name.localName == "objectgroup") { 58 | layers.addLayer(new TiledObjectLayer(elements[i])); 59 | } else if (name.localName == "imagelayer") { 60 | layers.addLayer(new TiledImageLayer(elements[i])); 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * Converts the map to a string containing the main properties for debugging purposes. 67 | * 68 | * @return The map in string format. 69 | */ 70 | public function toString():String { 71 | return [ 72 | "Version: " + version, 73 | "Orientation: " + orientation, 74 | "Width: " + width, 75 | "Height: " + height, 76 | "TileWidth: " + tileWidth, 77 | "TileHeight: " + tileHeight, 78 | "BackgroundColor: " + backgroundColor, 79 | "Properties: " + properties, 80 | "Tilesets: " + tilesets, 81 | "Layers: " + layers, 82 | ].join(", "); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledObject.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | import flash.geom.Point; 3 | 4 | /** 5 | * Represents a single within an in the map. 6 | */ 7 | public class TiledObject { 8 | public static const RECTANGLE:uint = 0; 9 | public static const ELLIPSE:uint = 1; 10 | public static const POLYGON:uint = 2; 11 | public static const POLYLINE:uint = 3; 12 | 13 | /** The name of the object. If unique, can be used to find the object by name. */ 14 | public var name:String; 15 | /** The type of the object. Can find all objects of a given type using this value. */ 16 | public var type:String; 17 | /** The global tile id of the object, if the object is a tile object. Otherwise, 0. */ 18 | public var gid:uint; 19 | /** The x value of the object. */ 20 | public var x:int; 21 | /** The y value of the object. */ 22 | public var y:int; 23 | /** The width of the object. */ 24 | public var width:uint; 25 | /** The height of the object. */ 26 | public var height:uint; 27 | /** Whether or not this object is visible. */ 28 | public var visible:Boolean; 29 | /** The properties of the object. */ 30 | public var properties:TiledProperties; 31 | /** The shape of the object, represented by TiledObject constants. */ 32 | public var shape:uint; 33 | /** A vector of points, if the object is a polygon or polyline. */ 34 | public var points:Vector.; 35 | 36 | public function TiledObject(tmx:XML) { 37 | name = "@name" in tmx ? tmx.@name : null; 38 | type = "@type" in tmx ? tmx.@type : null; 39 | gid = "@gid" in tmx ? tmx.@gid : 0; 40 | x = tmx.@x; 41 | y = tmx.@y; 42 | width = "@width" in tmx ? tmx.@width : 0; 43 | height = "@height" in tmx ? tmx.@height : 0; 44 | visible = !("@visible" in tmx && tmx.@visible == "0"); 45 | properties = new TiledProperties(tmx.properties); 46 | shape = RECTANGLE; 47 | 48 | if (tmx.ellipse.length() > 0) { 49 | shape = ELLIPSE; 50 | } else if (tmx.polygon.length() > 0) { 51 | shape = POLYGON; 52 | populatePoints(tmx.polygon.@points); 53 | } else if (tmx.polyline.length() > 0) { 54 | shape = POLYLINE; 55 | populatePoints(tmx.polyline.@points); 56 | } 57 | } 58 | 59 | /** 60 | * Given a space separate list of comma separate points, converts them into a 61 | * vector of points. 62 | */ 63 | private function populatePoints(pointString:String):void { 64 | points = new Vector.; 65 | var pointArray:Array = pointString.split(" "); 66 | for (var i:uint = 0; i < pointArray.length; i++) { 67 | var ps:Array = pointArray[i].split(","); 68 | if (ps.length != 2) { 69 | throw new ArgumentError("Invalid poly point: " + pointArray[i]); 70 | } 71 | points.push(new Point(parseFloat(ps[0]), parseFloat(ps[1]))); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledObjectLayer.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * Represents an object layer, parsed from an object. 4 | */ 5 | public class TiledObjectLayer extends TiledLayer { 6 | /** A vector of all the objects in the layer, in order. */ 7 | public var objects:Vector.; 8 | /** A map from type of object, to a vector of all objects of that type. */ 9 | public var typeMap:Object; 10 | /** A map from name of object, to a single object with that name. */ 11 | public var nameMap:Object; 12 | 13 | public function TiledObjectLayer(tmx:XML) { 14 | super(tmx); 15 | 16 | objects = new Vector.; 17 | typeMap = {}; 18 | nameMap = {}; 19 | 20 | var objectList:XMLList = tmx.object; 21 | for (var i:uint = 0; i < objectList.length(); i++) { 22 | var object:TiledObject = new TiledObject(objectList[i]); 23 | objects.push(object); 24 | if (object.name) { 25 | nameMap[object.name] = object; 26 | } 27 | if (object.type) { 28 | (typeMap[object.type] ||= new Vector.).push(object); 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * Given an index, returns the object at that position within the layer. 35 | * 36 | * @param index The index of the object. 37 | * @return The object. 38 | */ 39 | public function getObjectByIndex(index:uint):TiledObject { 40 | return objects[index]; 41 | } 42 | 43 | /** 44 | * Returns the last object in the layer with the passed name. If the names of your objects 45 | * are unique, you can always use this method to find an object by name. 46 | * 47 | * @param name The name of the object. 48 | * @return The object. 49 | */ 50 | public function getObjectByName(name:String):TiledObject { 51 | return nameMap[name]; 52 | } 53 | 54 | /** 55 | * Returns a vector of all objects in the layer with the passed type. 56 | * 57 | * @param type The type of the objects to find. 58 | * @return The vector of objects with the given type. 59 | */ 60 | public function getObjectsByType(type:String):Vector. { 61 | return typeMap[type]; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledProperties.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A container containing all properties of some part of the map. Many parts of the map, such 4 | * as tiles, objects, layers, etc, can contain a set of properties. Each will have a properties 5 | * value pointed to a TiledProperties object containing all properties. 6 | */ 7 | public class TiledProperties { 8 | /** The map containing the properties, keyed by name. */ 9 | public var properties:Object = {}; 10 | 11 | public function TiledProperties(properties:XMLList) { 12 | for (var i:uint = 0; i < properties.property.length(); i++) { 13 | set(properties.property[i].@name, properties.property[i].@value); 14 | } 15 | } 16 | 17 | /** 18 | * Returns the property for the given key. 19 | * 20 | * @param key The name of the property. 21 | * @return The property value. 22 | */ 23 | public function get(key:String):String { 24 | return properties[key]; 25 | } 26 | 27 | /** 28 | * Sets the property for the given key to the given value. 29 | * 30 | * @param key The name of the property. 31 | * @param value The property value. 32 | */ 33 | public function set(key:String, value:String):void { 34 | properties[key] = value; 35 | } 36 | 37 | /** 38 | * Creates a list of all properties. 39 | */ 40 | public function toString():String { 41 | var props:Vector. = new []; 42 | for (var key:String in properties) { 43 | props.push(key + "=" + properties[key]); 44 | } 45 | return "(" + props.join(", ") + ")"; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledReader.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * Reader for loading Tiled 0.9.0 maps. 4 | */ 5 | public class TiledReader { 6 | /** 7 | * Creates a new TiledReader. 8 | */ 9 | public function TiledReader() { 10 | } 11 | 12 | /** 13 | * Reads an embedded xml file and loads a TiledMap from it. 14 | * 15 | * @param map The embedded class containing the tmx file. 16 | * @return The fully parsed TiledMap. 17 | */ 18 | public function loadFromEmbedded(map:Class):TiledMap { 19 | return loadFromXML(new XML(new map)); 20 | } 21 | 22 | /** 23 | * Reads an XML object and loads a TiledMap from it. 24 | * 25 | * @param map The XML object in default tmx file format. 26 | * @return The fully parsed TiledMap. 27 | */ 28 | public function loadFromXML(map:XML):TiledMap { 29 | return new TiledMap(map); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledTerrain.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A container for the a terrain set within a tileset. 4 | */ 5 | public class TiledTerrain { 6 | /** The name of the terrain. */ 7 | public var name:String; 8 | /** The tile representing the terrain, -1 if none. */ 9 | public var tile:int; 10 | /** The terrain properties. */ 11 | public var properties:TiledProperties; 12 | 13 | public function TiledTerrain(terrain:XML) { 14 | name = terrain.@name; 15 | tile = terrain.@tile; 16 | properties = new TiledProperties(terrain.properties); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledTile.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A class describing a tile. Any tile with special properties, non-default terrain options, 4 | * etc, gets a tile representation to hold that information. 5 | */ 6 | public class TiledTile { 7 | /** Constant defining the first entry in a terrain array, the top left corner. */ 8 | public static const TOP_LEFT:uint = 0x0001; 9 | /** Constant defining the second entry in a terrain array, the top right corner. */ 10 | public static const TOP_RIGHT:uint = 0x0010; 11 | /** Constant defining the third entry in a terrain array, the bottom left corner. */ 12 | public static const BOTTOM_LEFT:uint = 0x0100; 13 | /** Constant defining the fourth entry in a terrain array, the bottom right corner. */ 14 | public static const BOTTOM_RIGHT:uint = 0x1000; 15 | /** A flag defining the top side of a tile, indicated by top left and top right flags being true. */ 16 | public static const TOP:uint = TOP_LEFT | TOP_RIGHT; 17 | /** A flag defining the left side of a tile, indicated by top left and bottom left flags being true. */ 18 | public static const LEFT:uint = BOTTOM_LEFT | TOP_LEFT; 19 | /** A flag defining the right side of a tile, indicated by top right and bottom right flags being true. */ 20 | public static const RIGHT:uint = TOP_RIGHT | BOTTOM_RIGHT; 21 | /** A flag defining the bottom side of a tile, indicated by bottom left and bottom right flags being true. */ 22 | public static const BOTTOM:uint = BOTTOM_LEFT | BOTTOM_RIGHT; 23 | 24 | /** A map containing a mapping from the index in the terrain array, to the corner it represents. */ 25 | private static const CORNER_MAP:Vector. = new [TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT]; 26 | 27 | /** The tile id of this tile. */ 28 | public var id:uint; 29 | /** The raw terrain, in the string format of a,b,c,d. */ 30 | public var rawTerrain:String; 31 | /** The terrain, a bitmask of TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT. */ 32 | public var terrain:uint; 33 | /** The probability of the tile. Used with terrain. */ 34 | public var probability:Number; 35 | /** Tile properties. */ 36 | public var properties:TiledProperties; 37 | /** Tile image. */ 38 | public var image:TiledImage; 39 | 40 | public function TiledTile(tmx:XML) { 41 | id = tmx.@id; 42 | rawTerrain = tmx.@terrain; 43 | terrain = csvToTerrain(tmx.@terrain); 44 | probability = "@probability" in tmx ? tmx.@probability : Number.NaN; 45 | properties = new TiledProperties(tmx.properties); 46 | image = new TiledImage(tmx.image); 47 | } 48 | 49 | /** 50 | * Converts a terrain array (in the string format of "a,b,c,d") to an integer representation 51 | * with the side flags. 52 | * 53 | * Any terrain layer in that corner feeds into this function. For raw tile informat, read from 54 | * TiledTile.rawTerrain. 55 | * 56 | * @param terrain The terrain array as a string. 57 | * @return The integer representation of the sides. 58 | */ 59 | private static function csvToTerrain(terrain:String):uint { 60 | var terrains:Array = terrain.split(","), value:uint = 0x0; 61 | for (var i:uint = 0; i < terrains.length; i++) { 62 | if (terrains[i].length > 0) { 63 | value += 0x1 << i; 64 | } 65 | } 66 | return value; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledTileLayer.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * Represents a single tile layer within a map. 4 | */ 5 | public class TiledTileLayer extends TiledLayer { 6 | /** The encoding used on the layer data. */ 7 | public var encoding:String; 8 | /** The compression used on the layer data. */ 9 | public var compression:String; 10 | /** The parsed layer data, uncompressed and unencoded. */ 11 | public var data:Array; 12 | 13 | public function TiledTileLayer(tmx:XML) { 14 | super(tmx); 15 | 16 | var dataNode:XML = tmx.data[0]; 17 | encoding = "@encoding" in dataNode ? dataNode.@encoding : null; 18 | compression = "@compression" in dataNode ? dataNode.@compression : null; 19 | data = TiledUtils.stringToTileData(dataNode.text(), width, encoding, compression); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledTileset.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | import flash.geom.Point; 3 | 4 | /** 5 | * A container holding properties for a single tileset within the map. 6 | */ 7 | public class TiledTileset { 8 | /** The first global tile id in the tileset. */ 9 | public var firstGid:uint; 10 | /** The name of the tilset. */ 11 | public var name:String; 12 | /** The maximum width of tiles in this tileset. */ 13 | public var tileWidth:uint; 14 | /** The maximum height of tiles in this tileset. */ 15 | public var tileHeight:uint; 16 | /** The spacing, in pixels, between the tiles in this tileset. */ 17 | public var spacing:uint; 18 | /** The margin around the tiles in this tileset. */ 19 | public var margin:uint; 20 | /** The offset, in pixels, for the tiles in this tileset. */ 21 | public var tileOffset:Point; 22 | /** The properties of the tileset. */ 23 | public var properties:TiledProperties; 24 | /** The tileset image. */ 25 | public var image:TiledImage; 26 | /** A map from terrain name to terrains contained within this tileset. */ 27 | public var terrain:Object; 28 | /** A map from gid to tile for all the non-standard tiles in the tileset. */ 29 | public var tiles:Object; 30 | 31 | public function TiledTileset(tmx:XML) { 32 | firstGid = tmx.@firstgid; 33 | name = tmx.@name; 34 | tileWidth = tmx.@tilewidth; 35 | tileHeight = tmx.@tileheight; 36 | spacing = "@spacing" in tmx ? tmx.@spacing : 0; 37 | margin = "@margin" in tmx ? tmx.@margin : 0; 38 | 39 | var offset:XMLList = tmx.tileoffset; 40 | tileOffset = offset.length() == 1 ? new Point(offset.@x, offset.@y) : new Point; 41 | 42 | image = new TiledImage(tmx.image); 43 | terrain = loadTerrain(tmx.terraintypes); 44 | tiles = loadTiles(tmx.tile); 45 | } 46 | 47 | /** 48 | * Given a tileset, loads all the terrains from the terraintypes object. 49 | * 50 | * @param tmx The terraintypes object. 51 | * @return The map from terrain name to terrain. 52 | */ 53 | private static function loadTerrain(tmx:XMLList):Object { 54 | var terrain:Object = {}; 55 | 56 | for (var i:uint = 0; i < tmx.terrain.length(); i++) { 57 | var node:TiledTerrain = new TiledTerrain(tmx.terrain[i]); 58 | terrain[node.name] = node; 59 | } 60 | 61 | return terrain; 62 | } 63 | 64 | /** 65 | * Given a list of tiles, builds a map from gid to tile. 66 | * 67 | * @param tmx The XMLList of objects. 68 | * @return The map from gid to tiles. 69 | */ 70 | private static function loadTiles(tmx:XMLList):Object { 71 | var tiles:Object = {}; 72 | 73 | for (var i:uint = 0; i < tmx.length(); i++) { 74 | var node:TiledTile = new TiledTile(tmx[i]); 75 | tiles[node.id] = node; 76 | } 77 | 78 | return tiles; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledTilesets.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | /** 3 | * A container that holds all tilesets within the map. 4 | */ 5 | public class TiledTilesets { 6 | /** A map from tileset tileset name to tileset. */ 7 | public var tilesets:Object = {}; 8 | /** A vector containing all tilesets in the order defined. */ 9 | public var tilesetsVector:Vector. = new []; 10 | 11 | public function TiledTilesets(tmx:XMLList) { 12 | for (var i:uint = 0; i < tmx.length(); i++) { 13 | addTileset(tmx[i]); 14 | } 15 | } 16 | 17 | /** 18 | * Given a object, parses the tileset and adds it to both the map and vector. 19 | * 20 | * @param tmx The object. 21 | */ 22 | private function addTileset(tmx:XML):void { 23 | var tileset:TiledTileset = new TiledTileset(tmx); 24 | tilesets[tileset.name] = tileset; 25 | tilesetsVector.push(tileset); 26 | } 27 | 28 | /** 29 | * Gets a tileset by index. 30 | * 31 | * @param index The index into the vector. 32 | * @return The tileset at the given index. 33 | */ 34 | public function getTileset(index:uint):TiledTileset { 35 | return tilesetsVector[index]; 36 | } 37 | 38 | /** 39 | * Gets a tileset by name. 40 | * 41 | * @param name The name of the tilset. 42 | * @return The tileset with the given name. 43 | */ 44 | public function getTilesetByName(name:String):TiledTileset { 45 | return tilesets[name]; 46 | } 47 | 48 | /** 49 | * Returns the number of tilesets in this map. 50 | * 51 | * @return The number of tilesets. 52 | */ 53 | public function size():uint { 54 | return tilesetsVector.length; 55 | } 56 | 57 | /** 58 | * Constructs a string containing the number of tilesets. 59 | */ 60 | public function toString():String { 61 | return size() + " tilesets"; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/TiledUtils.as: -------------------------------------------------------------------------------- 1 | package io.arkeus.tiled { 2 | import flash.utils.ByteArray; 3 | import flash.utils.Endian; 4 | 5 | import io.arkeus.tiled.base64.Base64; 6 | 7 | public class TiledUtils { 8 | /** 9 | * Converts a string in the format "#rrggbb" or "rrggbb" to the corresponding 10 | * uint representation. 11 | * 12 | * @param color The color in string format. 13 | * @return The color in uint format. 14 | */ 15 | public static function colorStringToUint(color:String):uint { 16 | return uint("0x" + color.replace("#", "")); 17 | } 18 | 19 | /** 20 | * Given a tiled data string for a single layer, returns an array of arrays containing 21 | * the tile information for that layer. Each inner array is a single row of the map. 22 | * 23 | * @param string The tiled data string. 24 | * @param mapWidth The width of the map, in tiles. 25 | * @param encoding The encoding used by tiled to generate the string. 26 | * @param compression The compression used by tiled to generate the string. 27 | * @return The array of arrays containing the parsed map data. 28 | */ 29 | public static function stringToTileData(string:String, mapWidth:uint, encoding:String, compression:String):Array { 30 | return byteArrayToMapData(decompressByteArray(decodeString(string, encoding), compression), mapWidth); 31 | } 32 | 33 | /** 34 | * Given a string and an encoding method, returns the string decoded as a byte array. 35 | * 36 | * @param string The string to decode. 37 | * @param encoding The encoding that was used to encode the string. 38 | * @return The decoded byte array. 39 | */ 40 | private static function decodeString(string:String, encoding:String):ByteArray { 41 | switch (encoding) { 42 | case "csv": 43 | return stringToByteArray(string); 44 | case "base64": 45 | return Base64.decode(string); 46 | default: 47 | throw new Error("Unsupported encoding: " + encoding); 48 | } 49 | } 50 | 51 | /** 52 | * Given a byte array and a compression method, returns the uncompressed byte array. 53 | * 54 | * @param data The byte array to decode. 55 | * @param compression The compression that was used to compress the byte array. 56 | * @return The uncompressed byte array. 57 | */ 58 | private static function decompressByteArray(data:ByteArray, compression:String):ByteArray { 59 | switch (compression) { 60 | case "gzip": 61 | throw new Error("gzip is unsupported, change Tiled preferences to use zlib"); 62 | case "zlib": 63 | data.uncompress(); 64 | data.endian = Endian.LITTLE_ENDIAN; 65 | return data; 66 | case null: 67 | return data; 68 | default: 69 | throw new Error("Unsupported compression: " + compression); 70 | } 71 | } 72 | 73 | /** 74 | * Given a string, returns the corresponding byte array representation of that string. 75 | * 76 | * @param string The string to convert. 77 | * @return The converted byte array. 78 | */ 79 | private static function stringToByteArray(string:String):ByteArray { 80 | var byteArray:ByteArray = new ByteArray; 81 | byteArray.writeUTFBytes(string); 82 | return byteArray; 83 | } 84 | 85 | /** 86 | * Given a decoded, uncompressed byte array, translates the byte array to an array 87 | * of arrays, where each inner array is a single row in the map, and each element 88 | * is a tile id. 89 | * 90 | * @param data The decoded, uncompressed byte array. 91 | * @param mapWidth The width of the map, in tiles. Each row should be the same width. 92 | * @return The array of arrays representing the map data. 93 | */ 94 | private static function byteArrayToMapData(data:ByteArray, mapWidth:uint):Array { 95 | var map:Array = [], row:Array = []; 96 | 97 | data.position = 0; 98 | 99 | while (data.position < data.length) { 100 | if (row.length == mapWidth) { 101 | map.push(row); 102 | row = []; 103 | } 104 | row.push(data.readInt()); 105 | } 106 | map.push(row); 107 | return map; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/io/arkeus/tiled/base64/Base64.as: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Jean-Philippe Auclair 3 | * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 4 | * Base64 library for ActionScript 3.0. 5 | * By: Jean-Philippe Auclair : http://jpauclair.net 6 | * Based on article: http://jpauclair.net/2010/01/09/base64-optimized-as3-lib/ 7 | * Benchmark: 8 | * This version: encode: 260ms decode: 255ms 9 | * Blog version: encode: 322ms decode: 694ms 10 | * as3Crypto encode: 6728ms decode: 4098ms 11 | * 12 | * Encode: com.sociodox.utils.Base64 is 25.8x faster than as3Crypto Base64 13 | * Decode: com.sociodox.utils.Base64 is 16x faster than as3Crypto Base64 14 | * 15 | * Optimize & Profile any Flash content with TheMiner ( http://www.sociodox.com/theminer ) 16 | */ 17 | package io.arkeus.tiled.base64 18 | { 19 | import flash.utils.ByteArray; 20 | 21 | public class Base64 22 | { 23 | private static const _encodeChars:Vector. = InitEncoreChar(); 24 | private static const _decodeChars:Vector. = InitDecodeChar(); 25 | 26 | public static function encode(data:ByteArray):String 27 | { 28 | var out:ByteArray = new ByteArray(); 29 | //Presetting the length keep the memory smaller and optimize speed since there is no "grow" needed 30 | out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms 31 | var i:int = 0; 32 | var r:int = data.length % 3; 33 | var len:int = data.length - r; 34 | var c:uint; //read (3) character AND write (4) characters 35 | var outPos:int = 0; 36 | while (i < len) 37 | { 38 | //Read 3 Characters (8bit * 3 = 24 bits) 39 | c = data[int(i++)] << 16 | data[int(i++)] << 8 | data[int(i++)]; 40 | 41 | out[int(outPos++)] = _encodeChars[int(c >>> 18)]; 42 | out[int(outPos++)] = _encodeChars[int(c >>> 12 & 0x3f)]; 43 | out[int(outPos++)] = _encodeChars[int(c >>> 6 & 0x3f)]; 44 | out[int(outPos++)] = _encodeChars[int(c & 0x3f)]; 45 | } 46 | 47 | if (r == 1) //Need two "=" padding 48 | { 49 | //Read one char, write two chars, write padding 50 | c = data[int(i)]; 51 | 52 | out[int(outPos++)] = _encodeChars[int(c >>> 2)]; 53 | out[int(outPos++)] = _encodeChars[int((c & 0x03) << 4)]; 54 | out[int(outPos++)] = 61; 55 | out[int(outPos++)] = 61; 56 | } 57 | else if (r == 2) //Need one "=" padding 58 | { 59 | c = data[int(i++)] << 8 | data[int(i)]; 60 | 61 | out[int(outPos++)] = _encodeChars[int(c >>> 10)]; 62 | out[int(outPos++)] = _encodeChars[int(c >>> 4 & 0x3f)]; 63 | out[int(outPos++)] = _encodeChars[int((c & 0x0f) << 2)]; 64 | out[int(outPos++)] = 61; 65 | } 66 | 67 | return out.readUTFBytes(out.length); 68 | } 69 | 70 | public static function decode(str:String):ByteArray 71 | { 72 | var c1:int; 73 | var c2:int; 74 | var c3:int; 75 | var c4:int; 76 | var i:int = 0; 77 | var len:int = str.length; 78 | 79 | var byteString:ByteArray = new ByteArray(); 80 | byteString.writeUTFBytes(str); 81 | var outPos:int = 0; 82 | while (i < len) 83 | { 84 | //c1 85 | c1 = _decodeChars[int(byteString[i++])]; 86 | if (c1 == -1) 87 | break; 88 | 89 | //c2 90 | c2 = _decodeChars[int(byteString[i++])]; 91 | if (c2 == -1) 92 | break; 93 | 94 | byteString[int(outPos++)] = (c1 << 2) | ((c2 & 0x30) >> 4); 95 | 96 | //c3 97 | c3 = byteString[int(i++)]; 98 | if (c3 == 61) 99 | { 100 | byteString.length = outPos 101 | return byteString; 102 | } 103 | 104 | c3 = _decodeChars[int(c3)]; 105 | if (c3 == -1) 106 | break; 107 | 108 | byteString[int(outPos++)] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2); 109 | 110 | //c4 111 | c4 = byteString[int(i++)]; 112 | if (c4 == 61) 113 | { 114 | byteString.length = outPos 115 | return byteString; 116 | } 117 | 118 | c4 = _decodeChars[int(c4)]; 119 | if (c4 == -1) 120 | break; 121 | 122 | byteString[int(outPos++)] = ((c3 & 0x03) << 6) | c4; 123 | } 124 | byteString.length = outPos 125 | return byteString; 126 | } 127 | 128 | public static function InitEncoreChar():Vector. 129 | { 130 | var encodeChars:Vector. = new Vector.(64, true); 131 | 132 | // We could push the number directly 133 | // but I think it's nice to see the characters (with no overhead on encode/decode) 134 | var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 135 | for (var i:int = 0; i < 64; i++) 136 | { 137 | encodeChars[i] = chars.charCodeAt(i); 138 | } 139 | 140 | return encodeChars; 141 | } 142 | 143 | public static function InitDecodeChar():Vector. 144 | { 145 | var decodeChars:Vector. = new [ 146 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 147 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 148 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 149 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 150 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 151 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 152 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 153 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 154 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 155 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 156 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 157 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; 162 | 163 | return decodeChars; 164 | } 165 | } 166 | } --------------------------------------------------------------------------------