Procedural Map Generation
I tried many different ways to generate map, and this way is very simple and good enough.
Reference - http://web.archive.org/web/20110825054218/http://properundead.com/2009/03/cave-generator.html
/**
* Copyright greentec ( http://wonderfl.net/user/greentec )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xPoa
*/
package {
import com.bit101.components.HUISlider;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
public class FlashTest extends Sprite {
public var _bitmapData:BitmapData;
public var _bitmap:Bitmap;
public var map:Array;
public var mapSize:int = 25;
public var mapSizeInit:int = 25;
public var mapSizeMax:int = 400;
public var mapCopy:Array;
public var landInitProb:Number = 0.7;
public var colorData:Object = {
LAND: 0x77a87e,
WATER: 0x3966a8,
SHORE: 0x133518
};
public var index:int = 0;
public var imgRect:Rectangle;
public var dir:Array = [[0, 0], [0, 1], [1, 0], [1, 1]];
public var landPercentHUISlider:HUISlider;
public function FlashTest() {
// write as3 code here..
_bitmapData = new BitmapData(465, 465, false, 0x292929);
_bitmap = new Bitmap(_bitmapData);
addChild(_bitmap);
initMapData();
imgRect = new Rectangle();
//var _label:Label = new Label(this, 10, mapSizeMax + 10, "Land %");
landPercentHUISlider = new HUISlider(this, 10, mapSizeMax + 10, "Land %");
landPercentHUISlider.labelPrecision = 0;
landPercentHUISlider.minimum = 1;
landPercentHUISlider.maximum = 99;
landPercentHUISlider.value = 70;
var _resetButton:PushButton = new PushButton(this, landPercentHUISlider.x, landPercentHUISlider.y + landPercentHUISlider.height + 5, "Reset", onReset);
addEventListener(Event.ENTER_FRAME, onLoop);
}
private function onReset(e:Event):void
{
if (hasEventListener(Event.ENTER_FRAME) == true)
{
removeEventListener(Event.ENTER_FRAME, onLoop);
}
index = 0;
mapSize = mapSizeInit;
landInitProb = landPercentHUISlider.value / 100;
_bitmapData.fillRect(_bitmapData.rect, 0x292929);
initMapData();
addEventListener(Event.ENTER_FRAME, onLoop);
}
private function initMapData():void
{
map = [];
var i:int;
for (i = 0; i < mapSize * mapSize; i += 1)
{
if (Math.random() < landInitProb)
{
map.push(1); //land
}
else
{
map.push(0); //water
}
}
}
private function onLoop(e:Event):void
{
var i:int;
var j:int;
var neighborNum:int;
var landNum:int = 0;
var _x:int;
var _y:int;
var cellIndex:int;
if (index < mapSize)
{
for (i = 0; i < mapSize; i += 1)
{
cellIndex = index * mapSize + i;
if (map[cellIndex] == 0)
{
imgRect.x = cellIndex % mapSize * int(mapSizeMax / mapSize);
imgRect.y = int(cellIndex / mapSize) * int(mapSizeMax / mapSize);
imgRect.width = int(mapSizeMax / mapSize);
imgRect.height = int(mapSizeMax / mapSize);
_bitmapData.fillRect(imgRect, colorData.WATER);
}
else if (map[cellIndex] == 1)
{
imgRect.x = cellIndex % mapSize * int(mapSizeMax / mapSize);
imgRect.y = int(cellIndex / mapSize) * int(mapSizeMax / mapSize);
imgRect.width = int(mapSizeMax / mapSize);
imgRect.height = int(mapSizeMax / mapSize);
_bitmapData.fillRect(imgRect, colorData.LAND);
}
}
index += 1;
}
else
{
if (mapSize < mapSizeMax)
{
index = 0;
removeEventListener(Event.ENTER_FRAME, onLoop);
mapCopy = [];
for (i = 0; i < mapSize * mapSize * 4; i += 1)
{
mapCopy.push(0);
}
for (i = 0; i < mapSize * mapSize; i += 1)
{
landNum = 0;
neighborNum = 1;
_x = i % mapSize;
_y = int(i / mapSize);
if (_x > 0)
{
neighborNum += 1;
if (map[i - 1] == 1)
{
landNum += 1;
}
}
if (_x < mapSize - 1)
{
neighborNum += 1;
if (map[i + 1] == 1)
{
landNum += 1;
}
}
if (_y > 0)
{
neighborNum += 1;
if (map[i - mapSize] == 1)
{
landNum += 1;
}
}
if (_y < mapSize - 1)
{
neighborNum += 1;
if (map[i + mapSize] == 1)
{
landNum += 1;
}
}
if (map[i] == 1)
{
landNum += 1;
}
for (j = 0; j < 4; j += 1)
{
if (Math.random() < landNum / neighborNum)
{
mapCopy[_x * 2 + dir[j][0] + (_y * 2 + dir[j][1]) * mapSize * 2] = 1;
}
else
{
mapCopy[_x * 2 + dir[j][0] + (_y * 2 + dir[j][1]) * mapSize * 2] = 0;
}
}
}
map = clone(mapCopy);
mapSize *= 2;
addEventListener(Event.ENTER_FRAME, onLoop);
}
else if(mapSize == mapSizeMax) //make shore
{
removeEventListener(Event.ENTER_FRAME, onLoop);
for (i = 0; i < map.length; i += 1)
{
_x = i % mapSize;
_y = int(i / mapSize);
if (map[i] == 1)
{
if (_x > 0)
{
if (map[i - 1] == 0)
{
map[i] = 2;
}
}
if (_x < mapSize - 1)
{
if (map[i + 1] == 0)
{
map[i] = 2;
}
}
if (_y > 0)
{
if (map[i - mapSize] == 0)
{
map[i] = 2;
}
}
if (_y < mapSize - 1)
{
if (map[i + mapSize] == 0)
{
map[i] = 2;
}
}
if (map[i] == 2)
{
imgRect.x = _x;
imgRect.y = _y;
imgRect.width = 1;
imgRect.height = 1;
_bitmapData.fillRect(imgRect, colorData.SHORE);
}
}
}
}
}
}
public function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
}
}