2D random dungeon with Minimap

by greentec forked from 2D random dungeon with FOV (diff: 79)
change log
- added minimap (with fog)
- increased the intensity of the light
♥10 | Line 557 | Modified 2015-08-18 20:19:08 | MIT License
play

ActionScript3 source code

/**
 * Copyright greentec ( http://wonderfl.net/user/greentec )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/jLiP
 */

// forked from greentec's 2D random dungeon with FOV
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.filters.BitmapFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import com.bit101.components.PushButton;
    
    /**
     * ...
     * @author ypc
     */
    [SWF(width="465", height="465", backgroundColor="#292929")]
    public class Main extends Sprite 
    {
        
        
        public var tileBitmapData:BitmapData;
        //public var tileBitmap:Bitmap;
        
        public var mapBitmapData:BitmapData;
        public var mapBitmap:Bitmap;
        
        public var mapArray:Array = [];
        public var mapWidth:int = 32;
        public var mapHeight:int = 32;
        
        
        //[Embed(source = "normal.png")]
        //public var tileImage:Class;
        
        //[Embed(source = "char1.png")]
        //public var tileImage:Class;
        //
        //public var colorMap:Object = { };
        //public var colorArray:Array = [];
        //public var colorBitmapIntegers:Array = [];
        
        public var tileColorArray:Array = [0x301800, 0x200000, 0xe07000, 0x804000, 0x603000, 0x402000, 0xa05000, 0xc06000, 0x101010, 0x505050, 0x606060, 0x404040, 0x303030, 0x202020];
        public var tileBitmapString:String = "011010100234445400101000023636440276226717643435056226731343633517636634133663340673434306343435023363400736343403336343033433450763343316633445176634441764443002667364063435450743453403334454127666330733445413346445173455450737344403434555066343540534545416334334010100101634434501101001043635450776767407643440056767670246434416336334063634011366333402734345036634341763454516366345076334541433334413365454076336450633444515463434076345441633444502445455143443451334454506363440035545550763343405445455036344000011001003445434010001110633440414767665136543550576767407343445023363440633434416636334174443400263645303343435073363440334340513363344066334441363444317344454023443430433434506343343036343450264343415343454067634451534450516634334055454540633434015554054076366440010100007664450001010000364334516737345063334011566773516334450063634341364454413636444023445050763444407634345163634431743545113633435166334441763463502334545063643340764345506363455025434540363334403434545036343450345455003636445063445450764340001101010023444540010100002363644114622671764343505622674134363351472763413366334037343430634343503236340073634340633634303343345037334331663344517663444176544300276736406343345154343340343545412666633076344441104644414345545073734440743343404514633011111111633433406464344167153440157677604363545034344450767111505734343024643441334345506363651176634340273434505434345176345331436634507643454101010111336444501155455043345111546343407635454147711110005510014344345153445450633763306700011076334341111110003334500076766001733643501577766063344041733437613663345057436340734344512663444163343441764643417444340073336330334343507336344033434051636363416634454166344451734445402636333053343450334335107634345026334341554345406764501163404051633436301010100063450661345405407636334067676630345664405440500026436451763734500563454000000051733444007363435137445441367776407344335076345440763434516363443174343411363345516633444176346350233344506364334076434550636345507543454036333450343454503634345034545400363644506344545076434000110101002344454001010010236364400462267176434350562245013436335147266341336633406734665111154550423634007363434033363640675111100433433166334451766343617376651005443640634354507434534063344331275543307335454133464431734554507373554054545550673435405345454163343351100001017344345011010010436354500100763076434400567676302464344100373340636340113663334027343450066343417634545163663450763345414333344133654540763364506364444154634340063454416334445024454441434434510044545013634400355454505633434000004550513450000110110554444340100011106555334147651551115435505767674073734450237400505665344166363341744434002636701033434350733634403343405133633605663344413634443173444540234434654334345063433430363434502643437153434540676344515344505167743343554545407334340155540540763774400101000076644500010100000643635107373450633340110007735100343400636343413644063100364440670540507634444046450351036344317470001136334351500064417634635023377450636433400663455063634550254345403633344034345450363434503454550036364450634454507643400011010100234445400101000023636440374446717643435056226731343633517646634133663340673434301043435033363400736343403336343005533450464343316633445176634441110553003467364053435450743453501111054147666331555545413346451111555050737344411114555066343511511115016334334010100101534434501101001043635450546551511513441115577450446434414336351073534011577633402734345054334351763154516446345076734541433434115765151063344450673444515453435007345401434444502445450143543451534400016463450035545150463443500511011043335000011011005445534011001110443400514767015146543550505577507345055023367010633435410577335174501500263675004343435005363400351510513363375056434541503445511011554023443630053434505743340105151410264343615043454157634551111451116734336015554551633454011551011076366440010100017665450001011100364334511557345063434011114773516334450057734341554454411636544043445050563444407354345143634531111115117733435167750341763463507265115073643340764650006363455025466410363334403433675036343450745455003636445063444400764340088888888888888888888888888888888889aa9bac8c9ab9bddc9baa9bd899aac8abcdddbd8bdcdbcd8adcdddd8addcd889cbdbbdd89dccbd89cd9bccd8ad9bdd8adbccdcd8b8dbdd89bbb9bcd8cbccbd89ccddcd8d8dd8889c9dcdbb88ddd9dc8acdd888d899cdd8bdcbdbbd8d8dcbbc8bdd88d89bccdd8d8ddc9cd8d8d8ddcd89888d88cdbdcdd88d8ddcd88d8d8ddd8b8bbd888dbcdbcd88bbc88dbcd8dd8d88b9cdb9c89c9ddc8bccdd8bc9cdd8888dcdc89cdc8bcbdd8dddcd8bddbcdcd88c9bc8bddc8bcbcd8dcccd8cdc9dbbdd8add8dddcbd8ddd8dccdd8d88dcbcdbd8acbd8cdd9cd8ccd88d8888d8db9bbcd89cd8ddbbcdd8cdd8d88b9d888dcccdc8add8d8dcbc88dd88889cdcd888dddcd88d8888dcdd8bc88cd8bdbddd8888dcd8d8dbbd8dd8bccddddc8cbcdc8cdd88d8abcd9dd888bcdcbbdd8dcdcd8dcbd888a9d9bd89bd8d8bdcdd88dcd89db9d8889bdccd9dc98d8cddd8bd8888bc9bbd88888888bcdb99d88889ccd8888dbbdd88a8cc8bcdbddc9b889dcbd89cd8dd8888b9bd8bcd99ccc888bdbdd89ddc88ddd89ddb88dccbcd8bdd8ddd89d9bbdddcd8ac888d8dcdb89cbd8d88bccbddddbdc88899d888dc889dccd8888ddcdb9dbdb8ccbdbc8d8889cbcdd8b998dddbccddc8a9ddbc888dbdbbddc89cbb88dddbbcc8abdccdd8d8bcdccdd89dcdd8dddddcc8bdccccdd88ddcddcd8cdddd88888ddd88888888888888888888888888888888888ba9bac8c9ab9bddc9baa9b9b9d8d888baccdbd8bdcdbcdcadcddbcbdc9dd889ac9cbdd89dccbd8dda9bccbdcd9b9d8a9bbcdcd8b8dbdd88ddb9bcbcdbccbd89cbcdbd8d8dd888dd8ddacbcbddd9dc8ab9cb88d899bc9cbdc88dbdddcdcbbc8bcbcdd89bccddd9dcb888d8dcd8ddcd89bcdcd8cdbdcbcbcbcdd88888888ddd8bcbccd88dbcdbdbcccbcc8dbcd8dd8d888dddb9c89b9cbdcbccdd8bc9cdd8888d88889cdc89cbddbcdddc8bddbcdcd88c9b88bddc8bcbccddcccd8cdc9dbbdd8add8dddcbd8ddd8dccdd8d88dcbcdbd8acbd8cdd9cd8ccd88d8888d8db9bbcd89cd8ddbbcdd88888d88b9d8d8dcccdc8add8d8dcb888dd88889cdcd888dddcd88d8888dc888bbc8dd8bdbddd8d88dcd8d8dbbd888bbccccddc8cbcdc8cdd88d8abcd9dd899ccdcdcdd8dcdcd8dcbd888a9d9bd89cdddcddcdd88dcd89db9d8889bdccd9cccdcddcdd8bd8888bc9bbd88888888bcdcdcdcd889ccd8888dbbdd88a8cc8bcdbddcdd889dcbd89cd8dd8888b9bd8bcd99ccc888bdbdd89ddc88d8d89ddb88dccbcd8bdd8ddd89d9bbd888d8ac888d8dcdb89cbd8d88bccbdd889dc88899d888dc889dccd8888ddcd8c9bdb8ccbdbc8d8889cbcdd8b998ddd89bcdc8a9ddbc888dbdbbddc89cbb888d9bbcc8abdccdd8d8bcdccdd89dcdd8d9bcccc8bdccccdd88ddcddcd8cdddd88bc8ddd88888888888888888888888888888888889aa98cd8b9ab9bddc9baa9bd899aac8abccdd8c9cdcdbcd8adcdddd89bbcd889ccdbbd89cdccbd89cd9bccd8ab9bdd8adbccdcd8b8dbdd89bbb9bcd8abccbd8dbcddcd8d8dd8889c9dcdbb8abcb9dc88dbb888d9bbcdd8bdcbdbbdcaccbbbc8dc888d89cbcdd8d8ddc9cd8abdccbcd888d8d88bdcdcdd88d8ddcd8accdccbd8dcbbd888dbcdbcd88bbc88acbbbdcbd8bb9bbb9b8889ddc8bcbdd8accccddd889cdcb9ccbbb88dd8bddcd8bcbbcccb88a9bdcbcbcdcc8cd8dcccd8cdc9dcddd89ddddcbddddcd88dccdd8d88d9ccdcd8bccddcccddddc8888d8888d8dcbdccd8bcddddcdccddcd88d8bb9d888dcccdc8adddcddccdddcd8888ccccd888ddddd8bdddcdcdcdcdd88cd8bbcbdd8888dcd8c9ccdbcddccdcd8ddbbddcdbdcdd88d88bdcddbcdcdddc8bdcddcdcddbcbd888889dccbcbcdcd8bcdddccccddbd9d888c98cddcccdcd88bccdbdcdbccdddbd889b98ddccdd88888cbdbdbdccdbbddd889ccc8ddd88d99b8bcccddccbcdddd888bccd8bc889cddd8bddccdcbccdcdddd89ddb88889bcccb8dcdcbbdccddcddcd8ac888d8d9dcddc8dcbccdddcdcddbdc88899d88cccdccd88dcddccbdcccdbdb8ccbdbc8ddcc9cbc8dcb99dcddcdcddc8a9ddbc88ddcdbbdd8cccbcccdddbbcc8abdccdd8d8bcdccd88cdccdccddddcc8bdccccdd88ddcddcd8cdddd88888ddd88888888888888888888888888888888889aa88abbc9ab9b88c9baa9bd899aac8abcd8bbddddcdbc88adcdddd8addcd889cbd8bddcccdcdc89cd9bccd8ad9bdd8adbc8dcddcdddcd89bbb9bc88cbccbd89ccd8cd8dcdcccd9c9dcdb888ddd9dc8acddd88dcdcddc8bdcbd8888d8dcbbc8bdd8dd88dccdcdd888d98d8d8d8ddcd89ddd888d8ddccd8ddd8d8d88d8d8ddd8bd8d8d88dbccd8d8cddd88dbcd8dd8d888d88b9c89dd8ddc9c88d8bc9cdd8888dc8d89c8c8b888c9cdd88ddddbcdcd88c9bc8b8dcdc8cc9cdbcd88ddc9dbbdd8adddd888dc8cdcdcdbcc88d8888cdbd8acbd888888c8dd8ddcbbcc8ddd8bbcd89cd8ddcbc8dd88d8dccbcd88d8cccdc8add8dcdcb8c8dc888ddcbdd8d8dddcd88d888ccc88bd99cddcdcdd8dd888dcd8d8dc8d8cb9bbcbdd8dcdd88c8cdd88d8acccc888bc9cccdc8d8888d8ddcbd888a9bcb888bcbccdddd8dbcdcdddb9d8889cdcc898dbbcdcc88dbdcd8d889bbd888cddd88cddcdcddd8ccddd8888bbdd88acdb8b888d8d8dd8dd88dd9cd88d8888b9bd8bc888d8d888888d889ddc88ddd89ddb88dc88888bd88d8d89d9bbdddcd8ac888d8d8db89cbd8d8dbccbddddbdc88899d888dc889dccd8888ddcdb9dbdb8ccbdbc8d8889cbcdd8b998dddbccddc8a9ddbc888dbdbbddc89cbb88dddbbcc8abdccdd8d8bcdccdd89dcdd8dddddcc8bdccccdd88ddcddcd8cdddd88888ddd";
        
        public var charColorArray:Array = [0x0, 0xff774e39, 0xff291f14, 0xff282038, 0xffd48c52, 0xff000000, 0xff452e30, 0xffa397db, 0xffebb385, 0xffc9ccf8, 0xffa17854, 0xfffcd9af, 0xff806cb3, 0xffc1ab84, 0xff838670, 0xff506ba5];
        public var charBitmapString:String = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000000000000000200022000000031445500000000000006202622220003718163500000000200212661622000379a863b850000000622612616228220699a134b850000002126116116662222777ca31445000000616a16a16166611622c63551550000006a1d1a16116228841ccccc3ccc3650021daaa111162e99b8437797cc773ee6561aa1666662155ffb8179997c793bde161a161aa162155ffbb4c9999c793bdea611611ada162888bbb41ad11311ddee166111aa66222288bbb81199c3ce6ee65266166622bbb888bbb81aad13ed6550026662222bbbb888bbb81199c3ce6ee65661a26222bbb888bbb41ad11311ddee161aa61aa622155ffbb4c9999c793bdea61da161da16255ffb8179997c793bde121a1a166111629b98417797cc773ee652616d1662661628841ccccc3ccc3650002161a1662226611622c63551550000002626111666622222777ca314450000000202611166228220699a134b850000000000216266222000379a863b850000000000262026222200037181f3500000000000020002200000003144550000000000000000002000000000110000000000000000000000000000000000000000000000000000000000000000000000000";
        
        public var roomMinWidth:int = 6;
        public var roomMaxWidth:int = 10;
        public var directionSelectMax:int = 4;
        public var directionSelectProb:int = 90;
        public var attenuationMin:int = 70; //make room smaller
        public var attenuationMax:int = 90;
        public var attenuationNumMax:int = 4;
        public var corridorMin:int = 1;
        public var corridorMax:int = 4;
        
        public var startPointX:int;
        public var startPointY:int;
        public var cameraPointX:int;
        public var cameraPointY:int;
        
        public var char:Character;
        
        public var fogBitmapData:BitmapData;
        public var fogBitmap:Bitmap;
        public var fogArray:Array = [];
        public var lightSourceDistance:int = 7;
        
        public var noiseBitmapData:BitmapData;
        
        public var minimapFogBitmapData:BitmapData;
        public var minimapBitmapData:BitmapData;
        public var minimapBitmap:Bitmap;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            
            stage.scaleMode = "noScale";
            
            tileBitmapData = new BitmapData(32 * 8, 32, true, 0x0);
            
            //initialize tile graphics with color compressed string
            var i:int, j:int;
            var index:int;
            
            for (i = 0; i < 256; i += 1)
            {
                for (j = 0; j < 32; j += 1)
                {
                    index = parseInt("0x" + tileBitmapString.substr(i * 32 + j, 1));
                    tileBitmapData.setPixel32(i, j, 0xff << 24 | tileColorArray[index]);
                }
            }
            
            
            //initialize map array
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    mapArray.push(-1);
                }
            }
            
            
            //make random dungeon
            var roomW:int = int(Math.random() * (roomMaxWidth - roomMinWidth)) + roomMinWidth;
            var roomH:int = int(Math.random() * (roomMaxWidth - roomMinWidth)) + roomMinWidth;
            var roomX:int = int(mapWidth / 2 - roomW / 2);
            var roomY:int = int(mapHeight / 2 - roomH / 2);
            makeRoom(roomX, roomY, roomW, roomH, 1);
            
            
            //make edge wall for natural map - south, east
            for (i = 0; i < mapWidth; i += 1)
            {
                mapArray[i * mapHeight + mapWidth - 1] = 1; //south
            }
            for (i = 0; i < mapHeight; i += 1)
            {
                mapArray[(mapWidth - 1) * mapHeight + i] = 1; //east
            }
            
            
            //draw tile to map
            mapBitmapData = new BitmapData(32 * mapWidth, 32 * mapHeight, false, 0x0);
            
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    index = Math.random() * 4;
                    
                    if (mapArray[i * mapHeight + j] == 0) //floor
                    {
                        index += 4;
                    }
                    
                    //draw tile
                    mapBitmapData.copyPixels(tileBitmapData, new Rectangle(32 * index, 0, 32, 32), new Point(i * 32, j * 32));
                    
                }
            }
            
            //set camera and starting point
            mapBitmap = new Bitmap(mapBitmapData);
            
            startPointX = int(Math.random() * roomW) + roomX;
            startPointY = int(Math.random() * roomH) + roomY;
            cameraPointX = startPointX - 7;
            cameraPointY = startPointY - 7;
            mapBitmap.x = -1 * 32 * cameraPointX;
            mapBitmap.y = -1 * 32 * cameraPointY;
            
            addChild(mapBitmap);
            
            
            //initialize character
            var bitmapData:BitmapData = new BitmapData(32, 32, true, 0x0);
            for (i = 0; i < 32; i += 1)
            {
                for (j = 0; j < 32; j += 1)
                {
                    index = parseInt("0x" + charBitmapString.substr(i * 32 + j, 1));
                    if (index != 0)
                    {
                        bitmapData.setPixel32(i, j, charColorArray[index]);
                    }
                }
            }
            
            char = new Character(startPointX, startPointY, new Bitmap(bitmapData));
            char.x = 32 * 7;
            char.y = 32 * 7;
            addChild(char);
            
            
            //character move listener
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            
            
            
            //initialize fog
            fogBitmapData = new BitmapData(32 * mapWidth, 32 * mapHeight, true, 0xff000000);
            fogBitmap = new Bitmap(fogBitmapData);
            
            fogBitmap.x = mapBitmap.x;
            fogBitmap.y = mapBitmap.y;
            addChild(fogBitmap);
            
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    fogArray.push( -1);
                }
            }
            
            //initialize fog noise
            noiseBitmapData = new BitmapData(32, 32, true, 0);
            noiseBitmapData.noise(int.MAX_VALUE * Math.random(), 0, 50, 7, true);
            noiseBitmapData.colorTransform(noiseBitmapData.rect, new ColorTransform(1, 1, 1, 0.1, 0, 0, 0, 0));
            //noiseBitmapData.noise(int.MAX_VALUE * Math.random(), 0, 255, 7);
            
            
            drawFog();
            
            
            //initialize minimap
            minimapBitmapData = new BitmapData(21 * 5, 21 * 5, true, 0x80292929);
            minimapBitmap = new Bitmap(minimapBitmapData);
            minimapBitmap.x = 465 - minimapBitmapData.width - 10;
            minimapBitmap.y = 10;
            addChild(minimapBitmap);
            
            minimapFogBitmapData = new BitmapData(21 * 5, 21 * 5, true, 0xff000000);
            
            drawMinimap();
            
            
            var button:PushButton = new PushButton(this, 465 - 110, 465 - 30, "Reset", onReset);
            
            //tileBitmapData.fillRect(new Rectangle(0, 0, 32, 32), 0xffff0000);
            
            //graphic compress code!!
            /*
            var bmp:Bitmap = new tileImage();
            var bitmapData:BitmapData = bmp.bitmapData;
            var _width:int = bitmapData.width;
            var _height:int = bitmapData.height;
            var color:uint;
            
            for (i = 0; i < _width; i += 1)
            {
                for (j = 0; j < _height; j += 1)
                {
                    color = bitmapData.getPixel32(i, j);
                    
                    if (colorMap.hasOwnProperty(color) == false)
                    {
                        colorMap[color] = 1;
                       colorArray.push(color);
                    }
                    
                    colorBitmapIntegers.push(colorArray.indexOf(color).toString(16));
                }
            }
            
            trace(colorArray.length);
            
            var str:String = "";
            for (i = 0; i < colorArray.length; i += 1)
            {
                str += "0x" + colorArray[i].toString(16) + ",";
            }
            trace(str);
            trace("");
            
            trace(colorBitmapIntegers.join(""));
            */
            
            
            //for blog
            //fogBitmap.visible = false;
            button.visible = false;
            //minimapBitmap.visible = false;
            
        }
        
        private function drawMinimap():void
        {
            minimapBitmapData.fillRect(minimapBitmapData.rect, 0x80292929);
            
            var i:int, j:int;
            var minScreenX:int = Math.max(0, cameraPointX - 3);
            var minScreenY:int = Math.max(0, cameraPointY - 3);
            var maxScreenX:int = Math.min(cameraPointX + 15 + 3, mapWidth);
            var maxScreenY:int = Math.min(cameraPointY + 15 + 3, mapHeight);
            var rect:Rectangle;
            
            for (i = minScreenX; i < maxScreenX; i += 1)
            {
                for (j = minScreenY; j < maxScreenY; j += 1)
                {
                    if (mapArray[i * mapHeight + j] == 0) //draw floor
                    {
                        rect = new Rectangle((i - minScreenX) * 5, (j - minScreenY) * 5, 5, 5);
                        minimapBitmapData.fillRect(rect, 0x80ffffff);
                        
                    }
                    
                }
            }
            
            //draw character
            rect = new Rectangle((char.posX - minScreenX) * 5 - 1, (char.posY - minScreenY) * 5 - 1, 5 + 2, 5 + 2);
            minimapBitmapData.fillRect(rect, 0x8000D4FF);
            
            //draw fog
            minimapFogBitmapData.fillRect(minimapFogBitmapData.rect, 0xff000000);
            
            for (i = minScreenX; i < maxScreenX; i += 1)
            {
                for (j = minScreenY; j < maxScreenY; j += 1)
                {
                    if (fogArray[i * mapHeight + j] != -1)
                    {
                        rect = new Rectangle((i - minScreenX) * 5, (j - minScreenY) * 5, 5, 5);
                        minimapFogBitmapData.fillRect(rect, 0x00000000);
                    }
                }
            }
            
            minimapBitmapData.draw(minimapFogBitmapData);
            
            
            
        }
        
        private function onReset(e:Event):void
        {
            var i:int, j:int;
            var index:int;
            
            //reset map array
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    mapArray[i * mapHeight + j] = -1;
                }
            }
            
            //make random dungeon
            var roomW:int = int(Math.random() * (roomMaxWidth - roomMinWidth)) + roomMinWidth;
            var roomH:int = int(Math.random() * (roomMaxWidth - roomMinWidth)) + roomMinWidth;
            var roomX:int = int(mapWidth / 2 - roomW / 2);
            var roomY:int = int(mapHeight / 2 - roomH / 2);
            makeRoom(roomX, roomY, roomW, roomH, 1);
            
            
            //make edge wall for natural map - south, east
            for (i = 0; i < mapWidth; i += 1)
            {
                mapArray[i * mapHeight + mapWidth - 1] = 1; //south
            }
            for (i = 0; i < mapHeight; i += 1)
            {
                mapArray[(mapWidth - 1) * mapHeight + i] = 1; //east
            }
            
            
            //draw tile to map
            mapBitmapData.fillRect(mapBitmapData.rect, 0x0);
            
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    index = Math.random() * 4;
                    
                    if (mapArray[i * mapHeight + j] == 0) //floor
                    {
                        index += 4;
                    }
                    
                    //draw tile
                    mapBitmapData.copyPixels(tileBitmapData, new Rectangle(32 * index, 0, 32, 32), new Point(i * 32, j * 32));
                    
                }
            }
            
            //set camera and starting point
            startPointX = int(Math.random() * roomW) + roomX;
            startPointY = int(Math.random() * roomH) + roomY;
            cameraPointX = startPointX - 7;
            cameraPointY = startPointY - 7;
            mapBitmap.x = -1 * 32 * cameraPointX;
            mapBitmap.y = -1 * 32 * cameraPointY;
            
            
            //reset character
            char.posX = startPointX;
            char.posY = startPointY;
            char.x = 32 * 7;
            char.y = 32 * 7;
            
            
            //reset fog
            fogBitmapData.fillRect(fogBitmapData.rect, 0xff000000);            
            
            fogBitmap.x = mapBitmap.x;
            fogBitmap.y = mapBitmap.y;
            
            for (i = 0; i < mapWidth; i += 1)
            {
                for (j = 0; j < mapHeight; j += 1)
                {
                    fogArray[i * mapHeight + j] = -1;
                }
            }
            
            drawFog();
            
            
        }
        
        private function drawFog():void
        {
            var i:int, j:int;
            var maxScreenX:int = Math.min(cameraPointX + 15, mapWidth);
            var maxScreenY:int = Math.min(cameraPointY + 15, mapHeight);
            var dist:int;
            
            
            //judge line of sight
            var lineSightArray:Array = [];
            for (i = cameraPointX; i < maxScreenX; i += 1)
            {
                for (j = cameraPointY; j < maxScreenY; j += 1)
                {
                    lineSightArray.push( -1);
                }
            }
            
            lineSightArray[(char.posX - cameraPointX) * 15 + (char.posY - cameraPointY)] = 0;
            
            var dx:Number;
            var dy:Number;
            var nowX:Number;
            var nowY:Number;
            
            for (i = -180; i <= 180; i += 2)
            {
                dx = Math.cos(Number(i) * 0.01744);
                dy = Math.sin(Number(i) * 0.01744);
                
                nowX = char.posX + dx + 0.5;
                nowY = char.posY + dy + 0.5;
                
                for (j = 0; j < 7; j += 1)
                {
                    lineSightArray[int(nowX - cameraPointX) * 15 + int(nowY - cameraPointY)] = 0;
                    
                    if (mapArray[int(nowX) * mapHeight + int(nowY)] != 0)
                    {
                        break;
                    }
                    
                    nowX += dx;
                    nowY += dy;
                    
                }
                
                
            }
            
            //initialize fogAlpha : visited -> 0
            for (i = cameraPointX; i < maxScreenX; i += 1)
            {
                for (j = cameraPointY; j < maxScreenY; j += 1)
                {
                    if (fogArray[i * mapHeight + j] > 0)
                    {
                        fogArray[i * mapHeight + j] = 0;
                    }
                }
            }
            
            
            //calculate distance from char (light source)
            for (i = cameraPointX; i < maxScreenX; i += 1)
            {
                for (j = cameraPointY; j < maxScreenY; j += 1)
                {
                    dist = Math.abs(char.posX - i) + Math.abs(char.posY - j);
                    if (dist <= lightSourceDistance)
                    {
                        if (lineSightArray[(i - cameraPointX) * 15 + (j - cameraPointY)] == 0) //can see
                        {
                            fogArray[i * mapHeight + j] = lightSourceDistance - dist;
                        }
                        else
                        {
                            //fogArray[i * mapHeight + j] = 0;
                        }
                        
                        
                    }
                }
            }
            
            
            //trace((char.posX - cameraPointX), (char.posY - cameraPointY));
            
            //draw fog
            fogBitmapData.fillRect(new Rectangle(cameraPointX * 32, cameraPointY * 32, (maxScreenX - cameraPointX) * 32, (maxScreenY - cameraPointY) * 32), 0x00ffffff);
            var fogRect:Rectangle;
            var fogAlpha:int;
            var color:uint;
            
            for (i = cameraPointX; i < maxScreenX; i += 1)
            {
                for (j = cameraPointY; j < maxScreenY; j += 1)
                {
                    fogRect = new Rectangle(i * 32, j * 32, 32, 32);
                    fogAlpha = fogArray[i * mapHeight + j];
                    //trace((i - cameraPointX), (j - cameraPointY));
                    //trace(lineSightArray[(i - cameraPointX) * mapHeight + (j - cameraPointY)]);
                    
                    if (fogAlpha == -1) //unvisited
                    {
                        fogBitmapData.fillRect(fogRect, 0xff000000);
                    }
                    else if (lineSightArray[(i - cameraPointX) * 15 + (j - cameraPointY)] == -1) //can't see, but visited
                    {
                        color = ((lightSourceDistance - 0) / (lightSourceDistance + 1) * 255) << 24; //+1 for visited place
                        fogBitmapData.fillRect(fogRect, color);
                        
                        //add noise
                        fogBitmapData.draw(noiseBitmapData, new Matrix(1, 0, 0, 1, i * 32, j * 32), null, "lighten");
                        
                    }
                    else
                    {
                        if (lineSightArray[(i - cameraPointX) * 15 + (j - cameraPointY)] == 0) //can see, visited
                        {
                            
                            color = ((lightSourceDistance - fogAlpha) / (lightSourceDistance + 1 + 2) * 255) << 24; //+1 for visited place, +2 for light intensity
                            fogBitmapData.fillRect(fogRect, color);
                            
                            //add noise
                            //fogBitmapData.applyFilter(noiseBitmapData, noiseBitmapData.rect, new Point(i * 32, j * 32), new BitmapFilter());
                            fogBitmapData.draw(noiseBitmapData, new Matrix(1, 0, 0, 1, i * 32, j * 32), null, "lighten");
                            //fogBitmapData.draw(noiseBitmapData, new Matrix(1, 0, 0, 1, i * 32, j * 32), null, "multiply");
                        }
                        
                    }
                    
                }
            }
            
            /*
            for (i = 0; i < 15; i += 1)
            {
                var str:String = "";
                
                for (j = 0; j < 15; j += 1)
                {
                    str = str.concat(String(lineSightArray[i * 15 + j]) + "\t");
                }
                
                trace(str);
            }
            */
            
        }
        
        private function onKeyDown(e:KeyboardEvent):void
        {
            switch(e.keyCode)
            {
                case 87: //w
                case 38: //Up
                    //wall check
                    if (char.posY - 1 >= 0 && 
                        mapArray[char.posX * mapHeight + (char.posY - 1)] == 0)
                    {
                        charMove(0, -1);
                        drawFog();
                        drawMinimap();
                    }
                    
                    
                    
                    break;
                
                case 83: //s
                case 40: //Down
                    //wall check
                    if (char.posY + 1 < mapHeight &&
                        mapArray[char.posX * mapHeight + (char.posY + 1)] == 0)
                    {
                        charMove(0, 1);
                        drawFog();
                        drawMinimap();
                    }
                    
                    break;
                    
                case 65: //a
                case 37: //Left
                    //wall check
                    if (char.posX - 1 >= 0 && 
                        mapArray[(char.posX - 1) * mapHeight + char.posY] == 0)
                    {
                        charMove( -1, 0);
                        drawFog();
                        drawMinimap();
                    }
                    
                    break;
                    
                case 68: //d
                case 39: //Right
                    //wall check
                    if (char.posX + 1 < mapWidth && 
                        mapArray[(char.posX + 1) * mapHeight + char.posY] == 0)
                    {
                        charMove(1, 0);
                        drawFog();
                        drawMinimap();
                    }
                    
                    break;
                
                
            }
        }
        
        private function charMove(moveX:int, moveY:int):void
        {
            //trace(char.posX, char.posY, cameraPointX, cameraPointY);
            
            char.posX += moveX;
            char.posY += moveY;
            
            /*
            //edge move - don't scroll map
            if (cameraPointX == 0)
            {
                char.x += moveX * 32;
                char.y += moveY * 32;
                
                //mapBitmap.y -= moveY * 32;
                return;
            }
            if (cameraPointY == 0)
            {
                char.x += moveX * 32;
                char.y += moveY * 32;
                
                //mapBitmap.x -= moveX * 32;
                return;
            }
            */
            
            //map scroll
            if (char.posX - cameraPointX == 3 && cameraPointX != 0)
            {
                mapBitmap.x += 32;
                cameraPointX -= 1;
                fogBitmap.x = mapBitmap.x;
                
                return;
            }
            if (cameraPointX + 14 - char.posX == 3 && cameraPointX != mapWidth - 15)
            {
                mapBitmap.x -= 32;
                cameraPointX += 1;
                fogBitmap.x = mapBitmap.x;
                
                return;
            }
            if (char.posY - cameraPointY == 3 && cameraPointY != 0)
            {
                mapBitmap.y += 32;
                cameraPointY -= 1;
                fogBitmap.y = mapBitmap.y;
                
                return;
            }
            if (cameraPointY + 14 - char.posY == 3 && cameraPointY != mapHeight - 15)
            {
                mapBitmap.y -= 32;
                cameraPointY += 1;
                fogBitmap.y = mapBitmap.y;
                
                return;
            }
            
            char.x += moveX * 32;
            char.y += moveY * 32;
            
            
        }
        
        
        private function makeRoom(roomX:int, roomY:int, roomWidth:int, roomHeight:int, scaleFactor:int):void
        {
            //trace("roomX: ", roomX, "\nroomY:", roomY, "\nroomWidth:", roomWidth, "\nroomHeight:", roomHeight);
            var i:int, j:int;
            
            //check possible
            if (roomX < 0 || roomX >= mapWidth || roomY < 0 || roomY >= mapHeight)
            {
                //trace("fail to batch");
                return;
            }
            if (roomX + roomWidth >= mapWidth || roomY + roomHeight >= mapHeight)
            {
                //trace("fail to batch room");
                return;
            }
            
            /*
            for (i = roomX; i < roomX + roomWidth; i += 1)
            {
                for (j = roomY; j < roomY + roomHeight; j += 1)
                {
                    if (mapArray[i * mapHeight + j] != -1)
                    {
                        //trace("not empty space");
                        return;
                    }
                }
            }
            */
            
            //make empty place
            for (i = roomX; i < roomX + roomWidth; i += 1)
            {
                for (j = roomY; j < roomY + roomHeight; j += 1)
                {
                    mapArray[i * mapHeight + j] = 0;
                }
            }
            
            if (scaleFactor == attenuationNumMax)
            {
                return;
            }
            
            //direction select
            var directionArray:Array = [0, 1, 2, 3];
            var directionIndex:int;
            var direction:int;
            
            var childRoomW:int;
            var childRoomH:int;
            var childRoomX:int;
            var childRoomY:int;
            
            var corridorIndex:int;
            var corridorLength:int;
            var corridorCellX:int;
            var corridorCellY:int;
            
            for (i = 0; i < directionSelectMax; i += 1)
            {
                if (Math.random() * 100 > directionSelectProb)
                {
                    continue;
                }
                
                childRoomW = roomWidth * (Math.random() * (attenuationMax - attenuationMin) + attenuationMin) / 100;
                childRoomH = roomHeight * (Math.random() * (attenuationMax - attenuationMin) + attenuationMin) / 100;
                
                directionIndex = int(Math.random() * directionArray.length);
                direction = directionArray.splice(directionIndex, 1);
                
                switch(direction)
                {
                    case 0: //N
                        
                        //roomW = int(Math.random() * (roomMaxWidth - roomMinWidth)) + roomMinWidth;
                        childRoomX = int(Math.random() * (roomWidth - childRoomW)) + roomX;
                        corridorLength = int(Math.random() * (corridorMax - corridorMin) + corridorMin);
                        childRoomY = roomY - childRoomH - corridorLength;
                        
                        //make corridor
                        corridorIndex = int(Math.random() * childRoomW) + childRoomX;
                        for (j = 0; j < corridorLength; j += 1)
                        {
                            corridorCellX = corridorIndex;
                            corridorCellY = roomY - 1 - j;
                            
                            if (corridorCellX < 0 || corridorCellX >= mapWidth || corridorCellY < 0 || corridorCellY >= mapHeight)
                            {
                                break;
                            }
                            
                            mapArray[corridorCellX * mapHeight + corridorCellY] = 0;
                            //trace("corridor:", corridorCellX, corridorCellY);
                        }
                        
                        break;
                        
                    case 1: //W
                        
                        corridorLength = int(Math.random() * (corridorMax - corridorMin) + corridorMin);
                        childRoomX = roomX - childRoomW - corridorLength;
                        childRoomY = int(Math.random() * (roomHeight - childRoomH)) + roomY;
                        
                        //make corridor
                        corridorIndex = int(Math.random() * childRoomH) + childRoomY;
                        for (j = 0; j < corridorLength; j += 1)
                        {
                            corridorCellX = roomX - 1 - j;
                            corridorCellY = corridorIndex;
                            
                            if (corridorCellX < 0 || corridorCellX >= mapWidth || corridorCellY < 0 || corridorCellY >= mapHeight)
                            {
                                break;
                            }
                            
                            mapArray[corridorCellX * mapHeight + corridorCellY] = 0;
                            //trace("corridor:", corridorCellX, corridorCellY);
                        }
                        
                        break;
                        
                    case 2: //S
                        
                        childRoomX = int(Math.random() * (roomWidth - childRoomW)) + roomX;
                        corridorLength = int(Math.random() * (corridorMax - corridorMin) + corridorMin);
                        childRoomY = roomY + roomHeight + corridorLength;
                        
                        //make corridor
                        corridorIndex = int(Math.random() * childRoomW) + childRoomX;
                        for (j = 0; j < corridorLength; j += 1)
                        {
                            corridorCellX = corridorIndex;
                            corridorCellY = roomY + roomHeight + j;
                            
                            if (corridorCellX < 0 || corridorCellX >= mapWidth || corridorCellY < 0 || corridorCellY >= mapHeight)
                            {
                                break;
                            }
                            
                            mapArray[corridorCellX * mapHeight + corridorCellY] = 0;
                            //trace("corridor:", corridorCellX, corridorCellY);
                        }
                        
                        break;
                        
                    case 3: //E
                        
                        corridorLength = int(Math.random() * (corridorMax - corridorMin) + corridorMin);
                        childRoomX = roomX + roomWidth + corridorLength;
                        childRoomY = int(Math.random() * (roomHeight - childRoomH)) + roomY;
                        
                        //make corridor
                        corridorIndex = int(Math.random() * childRoomH) + childRoomY;
                        for (j = 0; j < corridorLength; j += 1)
                        {
                            corridorCellX = roomX + roomWidth + j;
                            corridorCellY = corridorIndex;
                            
                            if (corridorCellX < 0 || corridorCellX >= mapWidth || corridorCellY < 0 || corridorCellY >= mapHeight)
                            {
                                break;
                            }
                            
                            mapArray[corridorCellX * mapHeight + corridorCellY] = 0;
                            //trace("corridor:", corridorCellX, corridorCellY);
                        }
                        
                        break;
                }
                
                //trace("make to:", roomX, roomY, childRoomX, childRoomY);
                makeRoom(childRoomX, childRoomY, childRoomW, childRoomH, scaleFactor + 1);
                
                
            }
            
            
            
            
        }
        
    }
 
}
Class
{
    import flash.display.Bitmap;
    import flash.display.Sprite;
    /**
     * ...
     * @author ypc
     */
    class Character extends Sprite
    {
        public var posX:int;
        public var posY:int;
        public var bitmap:Bitmap;
        
        public function Character(_x:int, _y:int, bmp:Bitmap) 
        {
            posX = _x;
            posY = _y;
            bitmap = bmp;
            addChild(bitmap);
        }
        
    }

}