PerlinNoise Terrain View
terrain color -
http://libnoise.sourceforge.net/tutorials/tutorial3.html
interpolate color function - http://snipplr.com/view/12514/as3-interpolate-color/
/**
* Copyright greentec ( http://wonderfl.net/user/greentec )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/to3H
*/
package
{
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.TextArea;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
//import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* @author ypc
*/
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=30)]
public class Main extends Sprite
{
public var tileSprite:Sprite;
public var tileBitmapData:BitmapData;
public var tileBitmap:Bitmap;
public var tileBitmapDataWidth:int = 400;
public var tileBitmapDataHeight:int = 400;
public var tileBitmapDataCellWidth:int;
public var tileBitmapDataCellHeight:int;
public var noiseSprite:Sprite;
public var noiseBitmap:Bitmap;
public var noiseBitmapData:BitmapData;
public var noiseBitmapDataWidth:int = 100;
public var noiseBitmapDataHeight:int = 100;
public var landCellnum:uint;
public var clone:BitmapData;
public var threshold:uint = 0x333333;
public var terrainColorDict:Array = [0x000080, 0x0000ff, 0x0080ff, 0xf0f040, 0x20a000, 0xe0e000, 0x808080, 0xffffff];
public var terrainColorNum:Array = [0, 0.125, 0.5, 0.53125, 0.5625, 0.6875, 0.875, 1];
public var randomSeed:int = Math.random() * int.MAX_VALUE;
public var offsets:Array = [];
public var speeds:Array = [];
public var numOctaves:int = 7;
public var numOctavesMax:int = 7;
public var channelOptions:int = Math.random() * 15 + 1;
public var stitch:Boolean = true;
public var fractalNoise:Boolean = false;
public var helpLabel:Label;
public var playButton:PushButton;
public var reverseButton:PushButton;
public var randomizeButton:PushButton;
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
var i:int;
for (i = 0; i < numOctavesMax; i += 1)
{
offsets[i] = new Point(0, 0);
speeds.push(new Point(Math.random()*8-4, Math.random()*8-4))
}
tileSprite = new Sprite();
addChild(tileSprite);
tileBitmapData = new BitmapData(tileBitmapDataWidth, tileBitmapDataHeight, false);
tileBitmap = new Bitmap(tileBitmapData);
tileSprite.addChild(tileBitmap);
//tileBitmap.blendMode = BlendMode.ADD;
noiseSprite = new Sprite();
addChild(noiseSprite);
noiseBitmapData = new BitmapData(noiseBitmapDataWidth, noiseBitmapDataHeight, false);
//noiseBitmapData.noise(randomSeed, 0, 255, 1, true);
noiseBitmapData.perlinNoise(noiseBitmapDataWidth, noiseBitmapDataHeight, numOctaves, randomSeed, false, fractalNoise, 7, true, offsets);
noiseBitmap = new Bitmap(noiseBitmapData);
noiseBitmap.x = 465 - 50;
//noiseSprite.addChild(noiseBitmap);
tileBitmapDataCellWidth = tileBitmapDataWidth / noiseBitmapDataWidth;
tileBitmapDataCellHeight = tileBitmapDataHeight / noiseBitmapDataHeight;
drawCell();
helpLabel = new Label(this, 10, 410, "numOctaves : " + String(numOctaves) + "\nrandomSeed : " + String(randomSeed) + "\nland : " + String(int(10000 * landCellnum / (noiseBitmapDataWidth * noiseBitmapDataHeight))/100) + " %");
playButton = new PushButton(this, 465 / 3, 410, "Play", onPlay);
playButton.toggle = true;
reverseButton = new PushButton(this, playButton.x + playButton.width, 410, "Reverse", onReverse);
randomizeButton = new PushButton(this, 465 / 3, playButton.y + playButton.height, "Randomize", onRandomize);
//addEventListener(Event.ENTER_FRAME, onEnterFrame);
//stage.addEventListener(MouseEvent.CLICK, onMouseClick);
}
private function onReverse(e:Event):void
{
var i:int;
for (i = 0; i < speeds.length; i += 1)
{
speeds[i].x *= -1;
speeds[i].y *= -1;
}
}
private function onRandomize(e:Event):void
{
randomSeed = Math.random() * int.MAX_VALUE;
//fractalNoise = Math.random() < 0.5 ? true : false;
//numOctaves = Math.random() * 4 + 4;
var i:int;
for (i = 0; i < numOctavesMax; i += 1)
{
speeds[i] = new Point(Math.random() * 8 - 4, Math.random() * 8 - 4);
}
noiseBitmapData.perlinNoise(noiseBitmapDataWidth, noiseBitmapDataHeight, numOctaves, randomSeed, false, fractalNoise, 7, true, offsets);
drawCell();
helpLabel.text = "numOctaves : " + String(numOctaves) + "\nrandomSeed : " + String(randomSeed) + "\nland : " + String(int(10000 * landCellnum / (noiseBitmapDataWidth * noiseBitmapDataHeight))/100) + " %";
}
private function onPlay(e:Event):void
{
if (e.target.selected == false)
//hasEventListener(Event.ENTER_FRAME))
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
playButton.label = "Play";
}
else
{
addEventListener(Event.ENTER_FRAME, onEnterFrame);
playButton.label = "Stop";
}
}
private function drawCell():void
{
var i:int;
var j:int;
var colorNum:Number;
var color:uint;
var k:int;
var t:Number;
landCellnum = 0;
for (i = 0; i < noiseBitmapDataWidth; i += 1)
{
for (j = 0; j < noiseBitmapDataHeight; j += 1)
{
colorNum = noiseBitmapData.getPixel(i, j) / 0xffffff;
//color = terrainColorDict[0];
for (k = 0; k < terrainColorNum.length - 1; k += 1)
{
if (terrainColorNum[k] <= colorNum && terrainColorNum[k+1] >= colorNum)
{
t = (colorNum - terrainColorNum[k]) / (terrainColorNum[k + 1] - terrainColorNum[k]);
color = interpolateColor(terrainColorDict[k], terrainColorDict[k + 1], t);
if (k >= 3)
{
landCellnum += 1;
}
}
}
tileBitmapData.fillRect(new Rectangle(i * tileBitmapDataCellWidth, j * tileBitmapDataCellHeight, tileBitmapDataCellWidth, tileBitmapDataCellHeight), color);
}
}
}
public static function interpolateColor(fromColor:uint, toColor:uint, progress:Number):uint
{
var q:Number = 1-progress;
var fromR:uint = (fromColor >> 16) & 0xFF;
var fromG:uint = (fromColor >> 8) & 0xFF;
var fromB:uint = fromColor & 0xFF;
var toR:uint = (toColor >> 16) & 0xFF;
var toG:uint = (toColor >> 8) & 0xFF;
var toB:uint = toColor & 0xFF;
var resultR:uint = fromR*q + toR*progress;
var resultG:uint = fromG*q + toG*progress;
var resultB:uint = fromB*q + toB*progress;
var resultColor:uint = resultR << 16 | resultG << 8 | resultB;
return resultColor;
}
private function onEnterFrame(e:Event):void
{
var i:int;
for (i = 0; i < numOctaves; i += 1)
{
offsets[i].x += speeds[i].x;
offsets[i].y += speeds[i].y;
}
noiseBitmapData.perlinNoise(noiseBitmapDataWidth, noiseBitmapDataHeight, numOctaves, randomSeed, false, fractalNoise, 7, true, offsets);
drawCell();
helpLabel.text = "numOctaves : " + String(numOctaves) + "\nrandomSeed : " + String(randomSeed) + "\nland : " + String(int(10000 * landCellnum / (noiseBitmapDataWidth * noiseBitmapDataHeight))/100) + " %";
}
}
}