Skip to content

Instantly share code, notes, and snippets.

@activeknowledge
Forked from shaunus84/Base64.as
Created September 22, 2012 21:21

Revisions

  1. @shaunus84 shaunus84 revised this gist Aug 6, 2012. 2 changed files with 184 additions and 92 deletions.
    220 changes: 147 additions & 73 deletions TMXTileMap.as
    Original file line number Diff line number Diff line change
    @@ -4,8 +4,8 @@ package
    import starling.display.Sprite;
    import starling.events.Event;

    import flash.display.Bitmap;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;
    @@ -17,125 +17,193 @@ package
    {
    // The TMX file to load
    private var _fileName:String;
    private var _loader:URLLoader = new URLLoader();

    private var _loader:URLLoader;
    private var _mapLoaded:Boolean;
    // XML of TMX file
    private var _TMX:XML;

    // Layers and tilesheet holders
    private var _layers:Vector.<TMXLayer> = new Vector.<TMXLayer>();
    private var _tilesheets:Vector.<TMXTileSheet> = new Vector.<TMXTileSheet>();

    private var _layers:Vector.<TMXLayer>;
    private var _tilesheets:Vector.<TMXTileSheet>;
    // variables pertaining to map description
    private var _numLayers:uint;
    private var _numTilesets:uint;
    private var _tilelistCount:uint = 0;
    private var _tilelistCount:uint;
    private var _mapWidth:uint;
    private var _tileHeight:uint;
    private var _tileWidth:uint;

    // used to get the correct tile from various tilesheets
    private var _gidLookup:Vector.<uint> = new Vector.<uint>();
    private var _gidLookup:Vector.<uint>;
    private var _embedTilesets:Vector.<Bitmap>;

    public function TMXTileMap():void
    {
    _mapLoaded = false;
    _fileName = "";
    _loader = new URLLoader();
    _numLayers = 0;
    _numTilesets = 0;
    _tilelistCount = 0;
    _mapWidth = 0;
    _tileHeight = 0;
    _tileWidth = 0;

    _layers = new Vector.<TMXLayer>();
    _tilesheets = new Vector.<TMXTileSheet>();
    _gidLookup = new Vector.<uint>();
    }


    public function TMXTileMap(file:String):void
    public function load(file:String):void
    {
    _fileName = file;

    trace(_fileName);

    _loader.addEventListener(flash.events.Event.COMPLETE, loadTilesets);
    _loader.load(new URLRequest(_fileName));
    }


    public function loadFromEmbed(tmx:XML, tilesets:Vector.<Bitmap>):void
    {
    _TMX = tmx;
    _embedTilesets = tilesets;

    loadEmbedTilesets();
    }

    // Getters ------------------------------------------
    public function layers():Vector.<TMXLayer>
    {
    return _layers;
    }

    public function tilesheets():Vector.<TMXTileSheet>
    {
    return _tilesheets;
    }

    public function numLayers():uint
    {
    return _numLayers;
    }

    public function numTilesets():uint
    {
    return _numTilesets;
    }

    public function mapWidth():uint
    {
    return _mapWidth;
    }

    public function tileHeight():uint
    {
    return _tileHeight;
    }

    public function tileWidth():uint
    {
    return _tileWidth;
    }

    // End getters --------------------------------------


    // get the number of tilsets from the TMX XML
    private function getNumTilesets():uint
    {
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    if (_mapLoaded)
    {
    if (_TMX.tileset[i] != null)
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    {
    count++;
    if (_TMX.tileset[i] != null)
    {
    count++;
    }
    }

    trace(count);
    return count;
    }

    trace(count);
    return count;
    return 0;
    }

    // get the number of layers from the TMX XML
    private function getNumLayers():uint
    {
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    if (_mapLoaded)
    {
    if (_TMX.layer[i] != null)
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    {
    count++;
    if (_TMX.layer[i] != null)
    {
    count++;
    }
    }
    }

    trace(count);
    return count;
    trace(count);
    return count;
    }
    return 0;
    }



    private function loadTilesets(event:flash.events.Event):void
    {
    trace("loading tilesets from file");
    _mapLoaded = true;

    _TMX = new XML(_loader.data);

    _mapWidth = _TMX.@width;
    _tileHeight = _TMX.@tileheight;
    _tileWidth = _TMX.@tilewidth;

    trace("map width" + _mapWidth);


    _numLayers = getNumLayers();
    _numTilesets = getNumTilesets();
    // _TMX.properties.property[1].@value;
    if (_TMX)
    {
    _mapWidth = _TMX.@width;
    _tileHeight = _TMX.@tileheight;
    _tileWidth = _TMX.@tilewidth;

    var tileSheet:TMXTileSheet = new TMXTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    tileSheet.addEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);
    _tilesheets.push(tileSheet);
    _gidLookup.push(_TMX.tileset[_tilelistCount].@firstgid);
    trace("map width" + _mapWidth);

    _numLayers = getNumLayers();
    _numTilesets = getNumTilesets();
    // _TMX.properties.property[1].@value;

    var tileSheet:TMXTileSheet = new TMXTileSheet();
    tileSheet.loadTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    tileSheet.addEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);
    _tilesheets.push(tileSheet);
    _gidLookup.push(_TMX.tileset[_tilelistCount].@firstgid);
    }
    }

    private function loadEmbedTilesets():void
    {
    trace("loading embedded tilesets");
    _mapLoaded = true;

    if (_TMX)
    {
    _mapWidth = _TMX.@width;
    _tileHeight = _TMX.@tileheight;
    _tileWidth = _TMX.@tilewidth;

    trace("map width" + _mapWidth);

    _numLayers = getNumLayers();
    _numTilesets = getNumTilesets();
    trace(_numTilesets);
    // _TMX.properties.property[1].@value;

    for (var i:int = 0; i < _numTilesets; i++)
    {
    var tileSheet:TMXTileSheet = new TMXTileSheet();
    trace(_TMX.tileset[i].@name, _embedTilesets[i], _TMX.tileset[i].@tilewidth, _TMX.tileset[i].@tileheight, _TMX.tileset[i].@firstgid - 1);
    tileSheet.loadEmbedTileSheet(_TMX.tileset[i].@name, _embedTilesets[i], _TMX.tileset[i].@tilewidth, _TMX.tileset[i].@tileheight, _TMX.tileset[i].@firstgid - 1);
    _tilesheets.push(tileSheet);
    _gidLookup.push(_TMX.tileset[i].@firstgid);
    }

    loadMapData();
    }
    }

    private function loadRemainingTilesets(event:starling.events.Event):void
    @@ -151,7 +219,8 @@ package
    else
    {
    trace(_TMX.tileset[_tilelistCount].@name);
    var tileSheet:TMXTileSheet = new TMXTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    var tileSheet:TMXTileSheet = new TMXTileSheet();
    tileSheet.loadTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    tileSheet.addEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);
    _gidLookup.push(_TMX.tileset[_tilelistCount].@firstgid);
    _tilesheets.push(tileSheet);
    @@ -160,40 +229,45 @@ package

    private function loadMapData():void
    {
    for (var i:int = 0; i < _numLayers; i++)
    if (_mapLoaded)
    {
    trace("loading map data");
    var ba:ByteArray = Base64.decode(_TMX.layer[i].data);
    ba.uncompress();
    for (var i:int = 0; i < _numLayers; i++)
    {
    trace("loading map data");
    var ba:ByteArray = Base64.decode(_TMX.layer[i].data);
    ba.uncompress();

    var data:Array = new Array();
    var data:Array = new Array();

    for (var j:int = 0; j < ba.length; j += 4)
    {
    // Get the grid ID
    for (var j:int = 0; j < ba.length; j += 4)
    {
    // Get the grid ID

    var a:int = ba[j];
    var b:int = ba[j + 1];
    var c:int = ba[j + 2];
    var d:int = ba[j + 3];
    var a:int = ba[j];
    var b:int = ba[j + 1];
    var c:int = ba[j + 2];
    var d:int = ba[j + 3];

    var gid:int = a | b << 8 | c << 16 | d << 24;
    data.push(gid);
    var gid:int = a | b << 8 | c << 16 | d << 24;
    data.push(gid);
    }

    var tmxLayer:TMXLayer = new TMXLayer(data);

    _layers.push(tmxLayer);
    }

    var tmxLayer:TMXLayer = new TMXLayer(data);

    _layers.push(tmxLayer);
    drawLayers();
    }

    drawLayers();
    }

    // draw the layers into a holder contained in a TMXLayer object
    private function drawLayers():void
    {
    trace("drawing layers");
    for (var i:int = 0; i < _numLayers; i++)
    {
    trace("drawing layers");
    var row:int = 0;
    var col:int = 0;
    for (var j:int = 0; j < _layers[i].getData().length; j++)
    @@ -215,7 +289,7 @@ package
    col += _tileWidth;
    }
    }

    // notify that the load is complete
    dispatchEvent(new starling.events.Event(starling.events.Event.COMPLETE));
    }
    56 changes: 37 additions & 19 deletions TMXTileSheet
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,6 @@ package
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    /**
    @@ -20,23 +19,26 @@ package
    // the name and file paths
    private var _name:String;
    private var _sheetFilename:String;

    // texture, atlas and loader
    private var _sheet:Bitmap;
    private var _textureAtlas:TextureAtlas;
    private var _imageLoader:Loader = new Loader();

    private var _startID:uint;

    private var _tileHeight:uint;
    private var _tileWidth:uint;
    private var _embedded:Boolean;

    public function TMXTileSheet(name:String, sheetFile:String, tileWidth:uint, tileHeight:uint, startID:uint):void
    public function TMXTileSheet():void
    {
    }

    public function loadTileSheet(name:String, sheetFile:String, tileWidth:uint, tileHeight:uint, startID:uint):void
    {
    _embedded = false;
    _name = name;
    _sheetFilename = sheetFile;
    _startID = startID;

    _tileHeight = tileHeight;
    _tileWidth = tileWidth;

    @@ -46,46 +48,62 @@ package
    _imageLoader.load(new URLRequest(_sheetFilename));
    }

    public function loadEmbedTileSheet(name:String, img:Bitmap, tileWidth:uint, tileHeight:uint, startID:uint):void
    {
    trace("creating TMX tilesheet");
    _embedded = true;
    _name = name;
    _startID = startID;

    _sheet = img;

    _tileHeight = tileHeight;
    _tileWidth = tileWidth;

    loadAtlas();
    }

    /*
    Load the image file needed for this tilesheet
    */
    Load the image file needed for this tilesheet
    */
    private function loadSheet(event:flash.events.Event):void
    {
    var sprite:DisplayObject = _imageLoader.content;
    _sheet = Bitmap(sprite);

    loadAtlas();
    }

    /*
    dynamically create a texture atlas to look up tiles
    */
    dynamically create a texture atlas to look up tiles
    */
    private function loadAtlas():void
    {
    trace("loading atlas");
    var numRows:uint = _sheet.height / _tileHeight;
    var numCols:uint = _sheet.width / _tileWidth;

    var id:int = _startID;

    var xml:XML = <Atlas></Atlas>;

    xml.appendChild(<TextureAtlas imagePath={_sheetFilename}></TextureAtlas>);
    for(var i:int = 0; i < numRows; i++)

    for (var i:int = 0; i < numRows; i++)
    {
    for(var j:int = 0; j < numCols; j++)
    for (var j:int = 0; j < numCols; j++)
    {
    id++;
    xml.child("TextureAtlas").appendChild(<SubTexture name={id} x = {j * _tileWidth} y={i * _tileHeight } width={_tileWidth} height={_tileHeight}/>);
    }
    }

    var newxml:XML = XML(xml.TextureAtlas);

    trace(newxml);

    _textureAtlas = new TextureAtlas(Texture.fromBitmap(_sheet), newxml);

    trace("done with atlas, dispatching");
    dispatchEvent(new starling.events.Event(starling.events.Event.COMPLETE));
    }

  2. @invalid-email-address Anonymous created this gist Jul 31, 2012.
    170 changes: 170 additions & 0 deletions Base64.as
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,170 @@
    /*
    * Copyright (C) 2012 Jean-Philippe Auclair
    * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
    * Base64 library for ActionScript 3.0.
    * By: Jean-Philippe Auclair : http://jpauclair.net
    * Based on article: http://jpauclair.net/2010/01/09/base64-optimized-as3-lib/
    * Benchmark:
    * This version: encode: 260ms decode: 255ms
    * Blog version: encode: 322ms decode: 694ms
    * as3Crypto encode: 6728ms decode: 4098ms
    *
    * Encode: com.sociodox.utils.Base64 is 25.8x faster than as3Crypto Base64
    * Decode: com.sociodox.utils.Base64 is 16x faster than as3Crypto Base64
    *
    * Optimize & Profile any Flash content with TheMiner ( http://www.sociodox.com/theminer )
    */
    package
    {
    import flash.utils.ByteArray;

    public class Base64
    {
    private static const _encodeChars:Vector.<int> = InitEncoreChar();
    private static const _decodeChars:Vector.<int> = InitDecodeChar();

    public static function encode(data:ByteArray):String
    {
    var out:ByteArray = new ByteArray();
    //Presetting the length keep the memory smaller and optimize speed since there is no "grow" needed
    out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms
    var i:int = 0;
    var r:int = data.length % 3;
    var len:int = data.length - r;
    var c:uint; //read (3) character AND write (4) characters
    var outPos:int = 0;
    while (i < len)
    {
    //Read 3 Characters (8bit * 3 = 24 bits)
    c = data[int(i++)] << 16 | data[int(i++)] << 8 | data[int(i++)];

    out[int(outPos++)] = _encodeChars[int(c >>> 18)];
    out[int(outPos++)] = _encodeChars[int(c >>> 12 & 0x3f)];
    out[int(outPos++)] = _encodeChars[int(c >>> 6 & 0x3f)];
    out[int(outPos++)] = _encodeChars[int(c & 0x3f)];
    }

    if (r == 1) //Need two "=" padding
    {
    //Read one char, write two chars, write padding
    c = data[int(i)];

    out[int(outPos++)] = _encodeChars[int(c >>> 2)];
    out[int(outPos++)] = _encodeChars[int((c & 0x03) << 4)];
    out[int(outPos++)] = 61;
    out[int(outPos++)] = 61;
    }
    else if (r == 2) //Need one "=" padding
    {
    c = data[int(i++)] << 8 | data[int(i)];

    out[int(outPos++)] = _encodeChars[int(c >>> 10)];
    out[int(outPos++)] = _encodeChars[int(c >>> 4 & 0x3f)];
    out[int(outPos++)] = _encodeChars[int((c & 0x0f) << 2)];
    out[int(outPos++)] = 61;
    }

    return out.readUTFBytes(out.length);
    }

    public static function decode(str:String):ByteArray
    {
    var c1:int;
    var c2:int;
    var c3:int;
    var c4:int;
    var i:int = 0;
    var len:int = str.length;

    var byteString:ByteArray = new ByteArray();
    byteString.writeUTFBytes(str);
    var outPos:int = 0;
    while (i < len)
    {
    //c1
    c1 = _decodeChars[int(byteString[i++])];
    if (c1 == -1)
    break;

    //c2
    c2 = _decodeChars[int(byteString[i++])];
    if (c2 == -1)
    break;

    byteString[int(outPos++)] = (c1 << 2) | ((c2 & 0x30) >> 4);

    //c3
    c3 = byteString[int(i++)];
    if (c3 == 61)
    {
    byteString.length = outPos
    return byteString;
    }

    c3 = _decodeChars[int(c3)];
    if (c3 == -1)
    break;

    byteString[int(outPos++)] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);

    //c4
    c4 = byteString[int(i++)];
    if (c4 == 61)
    {
    byteString.length = outPos
    return byteString;
    }

    c4 = _decodeChars[int(c4)];
    if (c4 == -1)
    break;

    byteString[int(outPos++)] = ((c3 & 0x03) << 6) | c4;
    }
    byteString.length = outPos
    return byteString;
    }

    public static function InitEncoreChar():Vector.<int>
    {
    var encodeChars:Vector.<int> = new Vector.<int>(64, true);

    // We could push the number directly
    // but I think it's nice to see the characters (with no overhead on encode/decode)
    var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    for (var i:int = 0; i < 64; i++)
    {
    encodeChars[i] = chars.charCodeAt(i);
    }

    return encodeChars;
    }

    public static function InitDecodeChar():Vector.<int>
    {

    var decodeChars:Vector.<int> = new <int>[
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1, 0, 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, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];

    return decodeChars;
    }

    }
    }


    32 changes: 32 additions & 0 deletions TMXLayer.as
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    package
    {
    import starling.display.Sprite;
    /**
    * @author shaun.mitchell
    */
    public class TMXLayer extends Sprite
    {
    private var _layerData:Array = new Array();
    private var _layerHolder:Sprite = new Sprite;

    public function TMXLayer(data:Array):void
    {
    _layerData = data;
    }

    public function getData():Array
    {
    return _layerData;
    }

    public function getHolder():Sprite
    {
    return _layerHolder;
    }

    public function drawLayer():void
    {
    addChild(_layerHolder);
    }
    }
    }
    241 changes: 241 additions & 0 deletions TMXTileMap.as
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,241 @@
    package
    {
    import starling.display.Image;
    import starling.display.Sprite;
    import starling.events.Event;

    import flash.events.Event;
    import flash.geom.Point;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;

    /**
    * @author shaun.mitchell
    */
    public class TMXTileMap extends Sprite
    {
    // The TMX file to load
    private var _fileName:String;
    private var _loader:URLLoader = new URLLoader();

    // XML of TMX file
    private var _TMX:XML;

    // Layers and tilesheet holders
    private var _layers:Vector.<TMXLayer> = new Vector.<TMXLayer>();
    private var _tilesheets:Vector.<TMXTileSheet> = new Vector.<TMXTileSheet>();

    // variables pertaining to map description
    private var _numLayers:uint;
    private var _numTilesets:uint;
    private var _tilelistCount:uint = 0;
    private var _mapWidth:uint;
    private var _tileHeight:uint;
    private var _tileWidth:uint;

    // used to get the correct tile from various tilesheets
    private var _gidLookup:Vector.<uint> = new Vector.<uint>();


    public function TMXTileMap(file:String):void
    {
    _fileName = file;

    _loader.addEventListener(flash.events.Event.COMPLETE, loadTilesets);
    _loader.load(new URLRequest(_fileName));
    }

    // Getters ------------------------------------------
    public function layers():Vector.<TMXLayer>
    {
    return _layers;
    }

    public function tilesheets():Vector.<TMXTileSheet>
    {
    return _tilesheets;
    }

    public function numLayers():uint
    {
    return _numLayers;
    }

    public function numTilesets():uint
    {
    return _numTilesets;
    }

    public function mapWidth():uint
    {
    return _mapWidth;
    }

    public function tileHeight():uint
    {
    return _tileHeight;
    }

    public function tileWidth():uint
    {
    return _tileWidth;
    }
    // End getters --------------------------------------


    // get the number of tilsets from the TMX XML
    private function getNumTilesets():uint
    {
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    {
    if (_TMX.tileset[i] != null)
    {
    count++;
    }
    }

    trace(count);
    return count;
    }

    // get the number of layers from the TMX XML
    private function getNumLayers():uint
    {
    var count:uint = 0;
    for (var i:int = 0; i < _TMX.children().length(); i++)
    {
    if (_TMX.layer[i] != null)
    {
    count++;
    }
    }

    trace(count);
    return count;
    }


    private function loadTilesets(event:flash.events.Event):void
    {
    _TMX = new XML(_loader.data);

    _mapWidth = _TMX.@width;
    _tileHeight = _TMX.@tileheight;
    _tileWidth = _TMX.@tilewidth;

    trace("map width" + _mapWidth);


    _numLayers = getNumLayers();
    _numTilesets = getNumTilesets();
    // _TMX.properties.property[1].@value;

    var tileSheet:TMXTileSheet = new TMXTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    tileSheet.addEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);
    _tilesheets.push(tileSheet);
    _gidLookup.push(_TMX.tileset[_tilelistCount].@firstgid);
    }

    private function loadRemainingTilesets(event:starling.events.Event):void
    {
    event.target.removeEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);

    _tilelistCount++;
    if (_tilelistCount >= _numTilesets)
    {
    trace("done loading tilelists");
    loadMapData();
    }
    else
    {
    trace(_TMX.tileset[_tilelistCount].@name);
    var tileSheet:TMXTileSheet = new TMXTileSheet(_TMX.tileset[_tilelistCount].@name, _TMX.tileset[_tilelistCount].image.@source, _TMX.tileset[_tilelistCount].@tilewidth, _TMX.tileset[_tilelistCount].@tileheight, _TMX.tileset[_tilelistCount].@firstgid - 1);
    tileSheet.addEventListener(starling.events.Event.COMPLETE, loadRemainingTilesets);
    _gidLookup.push(_TMX.tileset[_tilelistCount].@firstgid);
    _tilesheets.push(tileSheet);
    }
    }

    private function loadMapData():void
    {
    for (var i:int = 0; i < _numLayers; i++)
    {
    trace("loading map data");
    var ba:ByteArray = Base64.decode(_TMX.layer[i].data);
    ba.uncompress();

    var data:Array = new Array();

    for (var j:int = 0; j < ba.length; j += 4)
    {
    // Get the grid ID

    var a:int = ba[j];
    var b:int = ba[j + 1];
    var c:int = ba[j + 2];
    var d:int = ba[j + 3];

    var gid:int = a | b << 8 | c << 16 | d << 24;
    data.push(gid);
    }

    var tmxLayer:TMXLayer = new TMXLayer(data);

    _layers.push(tmxLayer);
    }

    drawLayers();
    }

    // draw the layers into a holder contained in a TMXLayer object
    private function drawLayers():void
    {
    for (var i:int = 0; i < _numLayers; i++)
    {
    var row:int = 0;
    var col:int = 0;
    for (var j:int = 0; j < _layers[i].getData().length; j++)
    {
    if (col > (_mapWidth - 1) * _tileWidth)
    {
    col = 0;
    row += _tileHeight;
    }

    if (_layers[i].getData()[j] != 0)
    {
    var img:Image = new Image(_tilesheets[findTileSheet(_layers[i].getData()[j])].textureAtlas.getTexture(String(_layers[i].getData()[j])));
    img.x = col;
    img.y = row;
    _layers[i].getHolder().addChild(img);
    }

    col += _tileWidth;
    }
    }

    // notify that the load is complete
    dispatchEvent(new starling.events.Event(starling.events.Event.COMPLETE));
    }

    private function findTileSheet(id:uint):int
    {
    var value:int = 0;
    var theOne:int;
    for (var i:int = 0; i < _tilesheets.length; i++)
    {
    if (_tilesheets[i].textureAtlas.getTexture(String(id)) != null)
    {
    theOne = i;
    }
    else
    {
    value = i;
    }
    }
    return theOne;
    }
    }
    }
    102 changes: 102 additions & 0 deletions TMXTileSheet
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    package
    {
    import starling.display.Sprite;
    import starling.events.Event;
    import starling.textures.Texture;
    import starling.textures.TextureAtlas;

    import flash.display.Bitmap;
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    /**
    * @author shaun.mitchell
    */
    public class TMXTileSheet extends Sprite
    {
    // the name and file paths
    private var _name:String;
    private var _sheetFilename:String;

    // texture, atlas and loader
    private var _sheet:Bitmap;
    private var _textureAtlas:TextureAtlas;
    private var _imageLoader:Loader = new Loader();

    private var _startID:uint;

    private var _tileHeight:uint;
    private var _tileWidth:uint;

    public function TMXTileSheet(name:String, sheetFile:String, tileWidth:uint, tileHeight:uint, startID:uint):void
    {
    _name = name;
    _sheetFilename = sheetFile;
    _startID = startID;

    _tileHeight = tileHeight;
    _tileWidth = tileWidth;

    trace("creating TMX tilesheet");

    _imageLoader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, loadSheet);
    _imageLoader.load(new URLRequest(_sheetFilename));
    }

    /*
    Load the image file needed for this tilesheet
    */
    private function loadSheet(event:flash.events.Event):void
    {
    var sprite:DisplayObject = _imageLoader.content;
    _sheet = Bitmap(sprite);

    loadAtlas();
    }

    /*
    dynamically create a texture atlas to look up tiles
    */
    private function loadAtlas():void
    {
    var numRows:uint = _sheet.height / _tileHeight;
    var numCols:uint = _sheet.width / _tileWidth;

    var id:int = _startID;

    var xml:XML = <Atlas></Atlas>;

    xml.appendChild(<TextureAtlas imagePath={_sheetFilename}></TextureAtlas>);

    for(var i:int = 0; i < numRows; i++)
    {
    for(var j:int = 0; j < numCols; j++)
    {
    id++;
    xml.child("TextureAtlas").appendChild(<SubTexture name={id} x = {j * _tileWidth} y={i * _tileHeight } width={_tileWidth} height={_tileHeight}/>);
    }
    }

    var newxml:XML = XML(xml.TextureAtlas);

    trace(newxml);

    _textureAtlas = new TextureAtlas(Texture.fromBitmap(_sheet), newxml);

    dispatchEvent(new starling.events.Event(starling.events.Event.COMPLETE));
    }

    public function get sheet():Bitmap
    {
    return _sheet;
    }

    public function get textureAtlas():TextureAtlas
    {
    return _textureAtlas;
    }
    }
    }