Wednesday, December 19, 2012

Flixel Multiple TileSets AutoTile Hack (WORK)

Hacking Flixel AutoTile to support over 16 tiles. AKA: Multiple auto tiling sets on same screen. Saving Original Function as I hack away at it: In FlxTileMap:
        /**
         * An internal function used by the binary auto-tilers.
         * 
         * @param    Index        The index of the tile you want to analyze.
         */
        protected function autoTile(Index:uint):void
        {
            if(_data[Index] == 0)
                return;
            
            _data[Index] = 0;
            if((Index-widthInTiles < 0) || (_data[Index-widthInTiles] > 0))         //UP    (JM: Very top of map, or tile above Index tile)
                _data[Index] += 1;
            if((Index%widthInTiles >= widthInTiles-1) || (_data[Index+1] > 0))         //RIGHT
                _data[Index] += 2;
            if((Index+widthInTiles >= totalTiles) || (_data[Index+widthInTiles] > 0)) //DOWN
                _data[Index] += 4;
            if((Index%widthInTiles <= 0) || (_data[Index-1] > 0))                     //LEFT
                _data[Index] += 8;
            if((auto == ALT) && (_data[Index] == 15))    //The alternate algo checks for interior corners
            {
                if((Index%widthInTiles > 0) && (Index+widthInTiles < totalTiles) && (_data[Index+widthInTiles-1] <= 0))
                    _data[Index] = 1;        //BOTTOM LEFT OPEN
                if((Index%widthInTiles > 0) && (Index-widthInTiles >= 0) && (_data[Index-widthInTiles-1] <= 0))
                    _data[Index] = 2;        //TOP LEFT OPEN
                if((Index%widthInTiles < widthInTiles-1) && (Index-widthInTiles >= 0) && (_data[Index-widthInTiles+1] <= 0))
                    _data[Index] = 4;        //TOP RIGHT OPEN
                if((Index%widthInTiles < widthInTiles-1) && (Index+widthInTiles < totalTiles) && (_data[Index+widthInTiles+1] <= 0))
                    _data[Index] = 8;         //BOTTOM RIGHT OPEN
            }
            _data[Index] += 1;
        }

Created fast re-mapping function to test logic for re-mapping indicies without the use of the slow "Math.floor"

private function indexToColumnNumberRemap(columnWidth:int):void
{
    //In Flixel: When using auto-tiling, you have 16 tiles to choose from.
    //   Tiles 1 - 16. Represented in based zero here by 0 - 15 
    //   If I want to edit Flixels: "autoTile" function in FlxTileMap, I will have to
    //   re-map a given tile-number to what tile-set it belongs to.
    //   this code attempts to do that re-map blazingly fast.
    //   faster than:     Math.ceil( index / 15 ) - 1;
    //   or faster than:  INV_15 = 1/15;  Math.ceil( index * INV_15 ) - 1;
    //
    //  [00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15] //USE TILE SET # 0;  0 - 15     
    //  [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] //USE TILE SET # 1;  16- 31     
    //  [32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47] //USE TILE SET # 2;  32- 47     
    //  [48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63] //USE TILE SET # 3;  48- 63    
    //  [64]
    
    var inv_ColumnWidth     :Number = 1 / columnWidth;
    var inv_ColumnWidthPlus1:Number = 1 / (columnWidth + 1);
    
    var shift:int;
    var finalVal:int;
    var I:int;
    for (var i:int = 0; i < 100; i++)
    {
        shift = int( i * inv_ColumnWidth );
        I = i + shift;
        finalVal = int( I * inv_ColumnWidthPlus1);
        
        trace(i +  " finalVal==" + finalVal);
    }
}

private function divTest_015():void
{
    // Proof of concept function: Remap logic:
    //  [00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15] //USE TILE SET # 0;  0 - 15     
    //  [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] //USE TILE SET # 1;  16- 31     
    //  [32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47] //USE TILE SET # 2;  32- 47     
    //  [48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63] //USE TILE SET # 3;  48- 63    
    //  [64]
    
    var I:int; //i shifted back one.
    var d:int;
    var m:int;
    var r:int;
    var finalVal:int;
    for (var i:int = 0; i < 100; i++)
    {
        m = int( (i) / 16);    
        I = i + m;
        finalVal = int(  I / (16 + 1)  ); //i divided by 17, rather than 16. Will shift off by one each cycle of 16,
        trace(i + " m==" + m + " finalVal==" + finalVal);
    }
    
}

As fun as that was... Remapping using: Is a bit faster. Here is my benchmark test:
        private function remapBenchmarkTest(columnWidth:int):void
        {
            //In Flixel: When using auto-tiling, you have 16 tiles to choose from.
            //   Tiles 1 - 16. Represented in based zero here by 0 - 15 
            //   If I want to edit Flixels: "autoTile" function in FlxTileMap, I will have to
            //   re-map a given tile-number to what tile-set it belongs to.
            //   this code attempts to do that re-map blazingly fast.
            //   faster than:     Math.ceil( index / 15 ) - 1;
            //   or faster than:  INV_15 = 1/15;  Math.ceil( index * INV_15 ) - 1;
            //
            //   update: actual calculation using floor;
            //   Math.ceil( (i + 1) / columnWidth) - 1);
            //
            //  [00][01][02][03][04][05][06][07][08][09][10][11][12][13][14][15] //USE TILE SET # 0;  0 - 15     
            //  [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] //USE TILE SET # 1;  16- 31     
            //  [32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47] //USE TILE SET # 2;  32- 47     
            //  [48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63] //USE TILE SET # 3;  48- 63    
            //  [64]
            
            var MAXTIMES:int = 9876543;
            
            var inv_ColumnWidth     :Number = 1 / columnWidth;
            var inv_ColumnWidthPlus1:Number = 1 / (columnWidth + 1);
            
            var shift:int;
            var finalVal:int;
            var I:int;
            var t:int; //for timer.
            t = getTimer();
            var i:int;
            for (i = 0; i < MAXTIMES; i++)
            {
                
                shift = int( i * inv_ColumnWidth );
                I = i + shift;
                finalVal = int( I * inv_ColumnWidthPlus1);
                
                //if (finalVal != ( Math.ceil( (i + 1) / columnWidth) - 1) ) { throw new Error("HAY!!!"); }
                //trace(i +  " finalVal==" + finalVal);
            }
            t = getTimer() - t;
            trace("time taken for optimized code:" + t);
            
            
            t = getTimer();
            for (i = 0; i < MAXTIMES; i++)
            {
                Math.ceil(i);
            }
            t = getTimer() - t;
            trace("time taken for just using Math.ceil" + t);
            
            t = getTimer();
            for (i = 0; i < MAXTIMES; i++)
            {
                finalVal = Math.ceil( (i + 1) / columnWidth) - 1;
            }
            t = getTimer() - t;
            trace("time taken for actual remap code using math.ceil" + t);
        }

No comments:

Post a Comment