From Dust

by wonderwhyer
Hehe, bought From Dust game few days ago, inspired me to return and work a little more on my old work I called Islands http://wonderwhy-er.deviantart.com/gallery/#/d2oe52m

It originally was my attempt to participate in LudumDare 17  http://www.ludumdare.com/compo/ludum-dare-17/?action=previewwhich theme was Islands. My idea kind of was similar to From Dust, save villagers from flood. But failed to do it in 48 hours :D

And now with From Dust inspiration and ludumdare 21 starting tomorrow I decided to play with it more as inspiration and publish it here ;) Have fun :)
♥8 | Line 294 | Modified 2011-08-20 03:12:59 | MIT License | (replaced)
play

Related images

ActionScript3 source code

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

package 
{
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.display.Loader;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.BlendMode;
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import com.bit101.components.*;
    import flash.display.GradientType;
    
    public class Main extends MovieClip
    {
        public var heightMap             : BitmapData
        public var mapWidth                : int         = 100;
        public var mapHeight             : int          = 100;
        public var grid                     : Vector.<GridCell>;
        public var waterBitmap             : BitmapData;
        public var positions             : Vector.<Pos>;
        public var scale                 : Number = 4;
        public var md                     : Boolean = false;
        

        
        public var ToolStrength             : Knob;
        public var ToolRadious             : Knob;
        public var SelectWater             : RadioButton;
        public var SelectEarth             : RadioButton;
        public var CreateIslandBtn         : PushButton;
        public var CreateRandomBtn         : PushButton;
        public var ClearBtn                 : PushButton;
        
        public var palpha:Number = 5;
        public var nalpha:Number = 1 / palpha;
        
        public var loader:Loader;
        
        public function Main():void {
            
            
            
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE,init);
            
            var url:String = "http://assets.wonderfl.net/images/related_images/0/02/0216/0216beeb7c40aff17d46a6ef5ef6b54c82d86c2c";     
            
            loader.load(new URLRequest(url),new LoaderContext(true));


            
            
        }
        
        public function init(e:Event):void
        {
            grid         = new Vector.<GridCell>(mapWidth*mapHeight,true);
            positions    = new Vector.<Pos>(mapWidth * mapHeight, true);
            
            heightMap     = new BitmapData(mapWidth, mapHeight, false, 0);
            waterBitmap = new BitmapData(mapWidth, mapHeight, true, 0);
            

            var DisObj:DisplayObject;
            
            ToolStrength = new Knob(this, 410, 300,"Strength");
            
            ToolRadious = new Knob(this, 410, 220,"Radious");
            ToolRadious.value = 5;
            ToolRadious.minimum = -50;
            ToolRadious.maximum = 50;
            
            SelectWater = new RadioButton(this, 410, 10, "Water", true,ToolChanged);
            SelectEarth = new RadioButton(this, 410, 30, "Earth", false,ToolChanged);
            SelectEarth.groupName = SelectWater.groupName = "tool";
            
            CreateIslandBtn = new PushButton(this, 405, 50, "Island", CreateIsland);
            CreateRandomBtn = new PushButton(this, 405, 75, "Random", Random);
            ClearBtn        = new PushButton(this, 405, 100, "Clear", ClearLand);
            
            CreateIslandBtn.width = CreateRandomBtn.width = ClearBtn.width = 45;
            
            DisObj = addChildAt(new Bitmap(waterBitmap),0);
            DisObj.scaleX = DisObj.scaleY = scale;
            
            DisObj = addChildAt(new Bitmap(heightMap),0);
            DisObj.scaleX = DisObj.scaleY = scale;
            
            ToolChanged();
            
            for (var i:uint = 0; i < positions.length; i++) {
                var pos:Pos = indexToPosition(i);
                var cell:GridCell = grid[i] = new GridCell(pos.x,pos.y,0,0,0);
            }
            
            for (i = 0; i < grid.length; i++) {
                var neighbours:Vector.<GridCell> = new Vector.<GridCell>();
                cell = grid[i];
                
                if (cell.x > 0)                 
                    neighbours.push(grid[positionToIndex(    cell.x-1, cell.y        )]);
                if (cell.x < mapWidth-1)         
                    neighbours.push(grid[positionToIndex(    cell.x+1, cell.y        )]);
                if (cell.y > 0)                 
                    neighbours.push(grid[positionToIndex(    cell.x,   cell.y - 1    )]);
                if (cell.y < mapHeight-1)         
                    neighbours.push(grid[positionToIndex(    cell.x,   cell.y + 1    )]);
                if (cell.y < mapHeight-1&&cell.x < mapWidth-1)         
                    neighbours.push(grid[positionToIndex(    cell.x+1,   cell.y + 1    )]);
                if (cell.y < mapHeight-1&&cell.x >0)         
                    neighbours.push(grid[positionToIndex(    cell.x-1,   cell.y + 1    )]);
                if (cell.y > 0&&cell.x < mapWidth-1)         
                    neighbours.push(grid[positionToIndex(    cell.x+1,   cell.y - 1    )]);
                if (cell.y > 0&&cell.x >0)         
                    neighbours.push(grid[positionToIndex(    cell.x-1,   cell.y - 1    )]);
                    
                cell.neighbours = neighbours;
            }
            addEventListener(Event.ENTER_FRAME, frame);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
            
            CreateIsland();
        }

        
        public function Random(e:Event=null):void
        {
            heightMap.perlinNoise(15 + Math.random() * 15, 15 + Math.random() * 15, Math.random() * 3, Math.random() * int.MAX_VALUE, true, Math.random() < 0.5, 7, true);
            InitMap();
        }
        
        public function CreateIsland(e:Event=null):void
        {
            heightMap.perlinNoise(20, 20, 2, Math.random()*int.MAX_VALUE, true,false, 7, true);
            var map:Sprite = new Sprite();
            var m:Matrix = new Matrix();
            m.createGradientBox(80, 80, 0, 10, 10);
            map.graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0], [1, 1], [50, 255], m);
            map.graphics.drawRect(0, 0, 100, 100);
            map.graphics.endFill();
            m.createGradientBox(20, 20, 0, 40, 40);
            map.graphics.beginGradientFill(GradientType.RADIAL, [0x303030, 0xFFFFFF], [1, 1], [0, 255], m);
            map.graphics.drawCircle(50, 50, 10);
            heightMap.draw(map, null, null, BlendMode.HARDLIGHT);
            InitMap()
        }
        
        public function ClearLand(e:Event=null):void
        {
            for (var i:uint = 0; i < positions.length; i++) {
                var pos:Pos = indexToPosition(i);
                var cell:GridCell = grid[i];
                cell.groundLevel = 0;
                cell.waterLevel = 0;
            }
            DrawMap();
        }
        
        public function InitMap(e:Event=null):void
        {
            for (var i:uint = 0; i < positions.length; i++) {
                var pos:Pos = indexToPosition(i);
                var cell:GridCell = grid[i];
                cell.groundLevel = heightMap.getPixel(pos.x, pos.y) % 256;
            }
            DrawMap();
        }
        
        public function ToolChanged(e:Event=null):void
        {
            if (SelectEarth.selected)
            {
                ToolStrength.maximum = 100;
                ToolStrength.minimum = -100;
                ToolStrength.value = 1;
            }
            else
            {
                ToolStrength.maximum = 100;
                ToolStrength.minimum = -100;
                ToolStrength.value = 10;
            }
        }
        
        public function DrawMap():void
        {
            var colors:BitmapData = (loader.content as Bitmap).bitmapData;
            for(var x:int=0;x<heightMap.width;x++){
                for (var y:int = 0; y < heightMap.width; y++) {
                    var cell:GridCell = grid[positionToIndex(x, y)];
                    heightMap.setPixel(x,y,colors.getPixel(Math.random()*(colors.width-1),255-cell.groundLevel));
                }        
            }
        }
        
        public function indexToPosition(index:uint):Pos {
            return new Pos(index % mapWidth, index / mapWidth);
        }
        
        public function positionToIndex(x:uint,y:uint):uint {
            return y * mapWidth + x;
        }
        
        public function mouseDown(e:Event):void {
            md = true;
        }
        
        public function mouseUp(e:Event):void {
            md = false;
        }
        
        public function roundTo(n:Number,p:Number):Number{
            return Math.round(p*n)/p;
        }
        
        public function frame(e:Event):void{
            //waterBitmap.fillRect(waterBitmap.rect, 0);
            if (md && mouseX < 400) {
                var cX:int = mouseX / scale;
                var cY:int = mouseY / scale;
                for (var xx:int = - ToolRadious.value; xx < ToolRadious.value;xx++)
                {
                    for (var yy:int = - ToolRadious.value; yy < ToolRadious.value;yy++)
                    {    
                        var multi:Number = 1 - Math.sqrt(Math.sqrt(xx * xx + yy * yy) / ToolRadious.value);
                        if (multi > 0)
                        {
                            var index:uint = positionToIndex(xx+cX, yy+cY);
                            if (index < grid.length) {
                                
                                if (SelectWater.selected)
                                {
                                    grid[index].waterLevel  = Math.max(0, grid[index].waterLevel + ToolStrength.value*multi );
                                }
                                else
                                {
                                    grid[index].groundLevel  = Math.min(255, Math.max(0, grid[index].groundLevel + ToolStrength.value*multi ));
                                    
                                }
                                
                            }
                        }
                    }
                }
                if (SelectEarth.selected)
                    DrawMap();
            }
            
            var level:Number;
            var pos:Pos;
            var weights:Vector.<Number> = new Vector.<Number>(8,true);

            var i:int;
            for (i = 0; i < grid.length; i++) {
                var cell:GridCell = grid[i];
                var neighbours:Vector.<GridCell> = cell.neighbours;
                
                var levelSum:Number = 0;
                var levelElems:int = 0;
                var cellLevel:Number = cell.groundLevel + cell.waterLevel+cell.waterLevelChange;
                for (var j:uint = 0; j < neighbours.length; j++) {
                    var neighbour:GridCell = neighbours[j];
                    var param:Number = cell.dmp*(neighbour.waterLevel+neighbour.groundLevel-cellLevel);
                    if (param < 0) {
                        levelElems++;
                        levelSum += param;
                        weights[j] = param;
                    }else {
                        weights[j] = 0;
                    }
                }
                if (levelSum < -cell.waterLevel) {
                    for (j = 0; j < neighbours.length; j++) {
                        if(weights[j]<0){
                            neighbour = neighbours[j];
                            neighbour.waterLevelChange += cell.waterLevel*(weights[j] / levelSum);
                        }
                    }
                    cell.waterLevelChange-= cell.waterLevel;
                }else {
                    cell.waterLevelChange += levelSum;
                    for (j = 0; j < neighbours.length; j++) {
                        neighbour = neighbours[j];
                        neighbour.waterLevelChange -= weights[j];
                    }
                }
            }
            
            for (i = 0; i < grid.length; i++) {
                cell = grid[i];
                cell.waterLevel = cell.waterLevel + cell.waterLevelChange;
                var aa:Number = cell.waterLevelChange-cell.dc;
                var bb:Number = cell.dc - cell.ddc;
                cell.dmp = 0.5 / (1+Math.abs(aa-bb));
                cell.ddc = cell.dc;
                cell.dc = cell.waterLevelChange;
                cell.waterLevelChange = 0;
                
                //waterLevel[i]= Math.max(0,waterLevel[i]+waterLevelChange[i]);
                level         = cell.waterLevel;
                //var change:Number = waterLevelChange[i];
                
                //pos = positions[i];
                if(level>0){
                    var a:uint = Math.round(128 * Math.min(palpha, level) * nalpha);
                    
                    waterBitmap.setPixel32(cell.x,cell.y,0xff + (a<<24));
                }else{
                    waterBitmap.setPixel32(cell.x,cell.y,0);
                }
            }
            
        }
    }
    
}

class Pos
{
    public var x:int;
    public var y:int;
    
    public function Pos(x:int,y:int) 
    {
        this.x = x;
        this.y = y;
    }
    
    public function toString():String {
        return "("+x.toString()+":"+y.toString()+")";
    }
}

class GridCell 
{
    public var neighbours        : Vector.<GridCell>;
    public var groundLevel        : Number;
    public var waterLevel        : Number;
    public var waterLevelChange    : Number;
    public var x                : Number;
    public var y                : Number;
    public var dc                : Number;
    public var ddc                : Number;
    public var dmp                : Number;
    
    public function GridCell(x:Number, y:Number, groundLevel : Number, waterLevel : Number, waterLevelChange: Number) {
        this.groundLevel         = groundLevel;
        this.waterLevel             = waterLevel;
        this.waterLevelChange     = waterLevelChange;
        this.x                     = x;
        this.y                     = y;
    }
}