In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Dungeon Generator

Get Adobe Flash player
by ChevyRay 24 Mar 2013
/**
 * Copyright ChevyRay ( http://wonderfl.net/user/ChevyRay )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/u1Ou
 */

package
{
    import flash.geom.Matrix;
    import flash.events.MouseEvent;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    
    //CLICK TO GENERATE A NEW MAZE!
    public class DungeonGenerator extends Sprite
    {
        //Dungeon settings
        public const MAZE_WIDTH:int = 13;
        public const MAZE_HEIGHT:int = 11;
        public const DUNGEON_EXPAND:int = 3;
        public const PASS_1:int = 0;
        public const PASS_2:int = 2;
        public const DUNGEON_SCALE:int = 4;
        
        //Directional constants
        public const RIGHT:uint = 0;
        public const LEFT:uint = 1;
        public const DOWN:uint = 2;
        public const UP:uint = 3;
        
        public var data:BitmapData;
        public var bitmap:Bitmap = new Bitmap();
        
        public function DungeonGenerator()
        {
            bitmap.scaleX = bitmap.scaleY = DUNGEON_SCALE;
            addChild(bitmap);
            
            stage.addEventListener(MouseEvent.CLICK, onClick);
            generate();
        }
        
        public function onClick(e:MouseEvent):void
        {
            generate();
        }
        
        public function generate():void
        {
            data = createMaze(MAZE_WIDTH, MAZE_HEIGHT);
            data = carveDungeon(data, DUNGEON_EXPAND, PASS_1, PASS_2);
            bitmap.bitmapData = data;
        }
        
        public function carveDungeon(maze:BitmapData, expand:int, ...mins):BitmapData
        {
            for each (var min:int in mins)
                maze = fractal(maze, expand, min);
            return maze;
        }
        
        public function fractal(data:BitmapData, exp:int, min:int):BitmapData
        {
            data = expand(data, exp);
            data = erode(data);
            if (min >= 0)
                data = clean(data, min);
            return data;
        }
        
        public function clean(data:BitmapData, min:int):BitmapData
        {
            var copy:BitmapData = data.clone();
            for (var x:int = 1; x < data.width - 1; x++)
            {
                for (var y:int = 1; y < data.height - 1; y++)
                {
                    if (getTile(data, x, y))
                    {
                        var count:int = 0;
                        if (getTile(data, x + 1, y))
                            count++;
                        if (getTile(data, x - 1, y))
                            count++;
                        if (getTile(data, x, y + 1))
                            count++;
                        if (getTile(data, x, y - 1))
                            count++;
                        if (count <= min)
                            setTile(copy, x, y, false);
                    }
                }
            }
            return copy;
        }
        
        public function erode(data:BitmapData):BitmapData
        {
            var copy:BitmapData = data.clone();
            var w:int = data.width - 1;
            var h:int = data.height - 1;
            var fill:Array = new Array();
            
            for (var x:int = 0; x < data.width; x++)
            {
                for (var y:int = 0; y < data.height; y++)
                {
                    if (!getTile(data, x, y))
                    {
                        fill.length = 0;
                        fill.push(getTile(data, x - 1, y));
                        fill.push(getTile(data, x + 1, y));
                        fill.push(getTile(data, x, y - 1));
                        fill.push(getTile(data, x, y + 1));
                        fill.push(getTile(data, x + 1, y + 1));
                        fill.push(getTile(data, x - 1, y - 1));
                        fill.push(getTile(data, x + 1, y - 1));
                        fill.push(getTile(data, x - 1, y + 1));
                        
                        if (fill[int(Math.random() * fill.length)])
                            setTile(copy, x, y, true);
                        else
                            setTile(copy, x, y, false);
                    }
                }
            }
            
            return copy;
        }
        
        public function expand(data:BitmapData, scale:int):BitmapData
        {
            var newData:BitmapData = createData(data.width * scale, data.height * scale);
            newData.draw(data, new Matrix(scale, 0, 0, scale));
            return newData;
        }
        
        public function createMaze(width:int, height:int):BitmapData
        {
            var data:BitmapData = createData(width, height);
            var xStack:Array = [];
            var yStack:Array = [];
            var sides:Array = [];
            
            data.fillRect(data.rect, 0xFFFFFFFF);
            
            //Pick random start point
            var x:int = 1 + int(Math.random() * (width / 2)) * 2;
            var y:int = 1 + int(Math.random() * (height / 2)) * 2;
            xStack.push(x);
            yStack.push(y);
            
            //Maze generation loop
            while (xStack.length > 0)
            {
                x = xStack[xStack.length - 1];
                y = yStack[yStack.length - 1];
                sides.length = 0;
                
                if (getTile(data, x + 2, y))
                    sides.push(RIGHT);
                if (getTile(data, x - 2, y))
                    sides.push(LEFT);
                if (getTile(data, x, y + 2))
                    sides.push(DOWN);
                if (getTile(data, x, y - 2))
                    sides.push(UP);
                
                if (sides.length > 0)
                {
                    var side:int = sides[int(Math.random() * sides.length)];
                    switch (side)
                    {
                        case RIGHT:
                            setTile(data, x + 1, y, false);
                            setTile(data, x + 2, y, false);
                            xStack.push(x + 2);
                            yStack.push(y);
                            break;
                        case LEFT:
                            setTile(data, x - 1, y, false);
                            setTile(data, x - 2, y, false);
                            xStack.push(x - 2);
                            yStack.push(y);
                            break;
                        case DOWN:
                            setTile(data, x, y + 1, false);
                            setTile(data, x, y + 2, false);
                            xStack.push(x);
                            yStack.push(y + 2);
                            break;
                        case UP:
                            setTile(data, x, y - 1, false);
                            setTile(data, x, y - 2, false);
                            xStack.push(x);
                            yStack.push(y - 2);
                            break;
                    }
                }
                else
                {
                    xStack.pop();
                    yStack.pop();
                }
            }
            
            return data;
        }
        
        public function createData(width:int, height:int):BitmapData
        {
            return new BitmapData(width, height, false, 0xFFFFFF);
        }
        
        public function getTile(data:BitmapData, x:int, y:int):Boolean
        {
            if (x < 0 || y < 0 || x >= data.width || y >= data.height)
                return false;
            return data.getPixel(x, y) > 0x000000;
        }
        
        public function setTile(data:BitmapData, x:int, y:int, solid:Boolean):void
        {
            data.setPixel(x, y, solid ? 0xFFFFFF : 0x000000);
        }
    }
}