var bitmapData:BitmapData = new BitmapData(100, 100, false, 0xFFFFFF);
var noises:Vector.<Number> noises = PerlinNoise.getNoise(100, 100, 3, 7, 0.6, 20);
for (var x:int = 0; x < width; x++)
{
for (var y:int = 0; y < height - 10; y++)
{
var noise:Number = noises[x + y * width];
if (noise > 0.4 && noise < 0.6)
{
bitmapData.setPixel(x, y + 10, 0xFFFFFF);
}
if (noise > 0.8 && noise < 1.0)
{
bitmapData.setPixel(x, y + 10, 0x0000FF);
}
if (noise > 0.0 && noise < 0.2 && y >= 70)
{
bitmapData.setPixel(x, y + 10, 0xFF0000);
}
}
}
var bmp:Bitmap = new Bitmap(bitmapData);
bmp.scaleX = 6.0;
bmp.scaleY = 6.0;
addChild(bmp);
public final class Rand
{
static private var _seed:uint;
public function set seed(val:uint):void
{
if (val != 0)
{
_seed = val;
}
else
{
_seed = uint(Math.random() * uint.MAX_VALUE);
}
}
public function get seed():uint
{
return _seed;
}
public function nextInt(min:int, max:int):int
{
_seed = 214013 * _seed + 2531011;
return min + (_seed ^ (_seed >> 15)) % (max - min + 1);
}
public function nextNumber(min:Number, max:Number):Number
{
_seed = 214013 * _seed + 2531011;
return min + (_seed >>> 16) * (1.0 / 65535.0) * (max - min);
}
}
public final class PerlinNoise
{
private static var _rand:Rand = new Rand();
public static function randomize(seed:uint):void
{
_rand.seed = seed;
}
public static function getNoise(width:int, height:int,
startOctave:int, endOctave:int, persistence:Number, smoothAmount:Number):Vector.<Number>
{
var valueNoiseMap:Vector.<Number> = new Vector.<Number>(width * height);
var cellSize:Number = width / Math.pow(2, endOctave);
var integerX:int = Math.floor((width - 1) / cellSize);
var integerY:int = Math.floor((height - 1) / cellSize);
var octaveSize:Number = Math.pow(2, endOctave + 1) - Math.pow(2, endOctave) + 1;
var nodeCount:int = (integerY + 1) * octaveSize + integerX + 2;
var randomTree:Vector.<Number> = new Vector.<Number>(nodeCount);
for (var i:int = 0; i < randomTree.length; ++i)
{
randomTree[i] = _rand.nextNumber(0.0, 0.9);
}
for(var y:int = 0; y < height; ++y)
{
for(var x:int = 0; x < width; ++x)
{
valueNoiseMap[y * width + x] = 0;
for (var i:int = startOctave; i <= endOctave; ++i)
{
var cellSize:Number = width / Math.pow(2, i);
var integerX:int = Math.floor(x / cellSize);
var integerY:int = Math.floor(y / cellSize);
var fractionalX:Number = (x - integerX * cellSize) / cellSize;
var fractionalY:Number = (y - integerY * cellSize) / cellSize;
var octaveSize:Number = Math.pow(2, i + 1) - Math.pow(2, i) + 1;
var i1 = interpolate(randomTree[integerY * octaveSize + integerX],
randomTree[integerY * octaveSize + integerX + 1],
fractionalX);
var i2 = interpolate(randomTree[(integerY + 1) * octaveSize + integerX],
randomTree[(integerY + 1) * octaveSize + integerX + 1],
fractionalX);
valueNoiseMap[y * width + x] +=
interpolate(i1 , i2 , fractionalY) * Math.pow(persistence, i - startOctave);
}
}
}
smooth(width, height, valueNoiseMap, smoothAmount);
normalize(width, height, valueNoiseMap, 0, 1);
return valueNoiseMap;
}
private static function smooth(width:int, height:int, noise:Vector.<Number>, amount:int):void
{
for (var i:int = 0; i < amount; ++i)
{
for (var y:int = 0; y < height; ++y)
{
for(var x:int = 0; x < width; ++x)
{
var xMinus1:int = x == 0 ? width - 1 : x - 1;
var yMinus1:int = y == 0 ? height - 1 : y - 1;
var xPlus1:int = (x + 1) % width;
var yPlus1:int = (y + 1) % height;
var corners:Number = (noise[yMinus1 * width + xMinus1] +
noise[yMinus1 * width + xPlus1] +
noise[yPlus1 * width + xPlus1] +
noise[yPlus1 * width + xMinus1]) / 16.0;
var sides:Number = (noise[y * width + xMinus1] +
noise[y * width + xPlus1] +
noise[yMinus1 * width + x] +
noise[yPlus1 * width + x]) / 8.0;
var center:Number = noise[y * width + x] / 4.0;
noise[y * width + x] = corners + sides + center;
}
}
}
}
private static function normalize(width:int, height:int,
noise:Vector.<Number>, minimum:Number, maximum:Number):void
{
var min:Number = Number.MAX_VALUE;
var max:Number = -Number.MAX_VALUE;
// Calculate min and max range used to normalize with
for (var y:int = 0; y < height; ++y)
{
for(var x:int = 0; x < width; ++x)
{
min = Math.min(min, noise[y * width + x]);
max = Math.max(max, noise[y * width + x]);
}
}
// Normalize the range to 0 to 1
for (var y:int = 0; y < height; ++y)
{
for(var x:int = 0; x < width; ++x)
{
noise[y * width + x] = (noise[y * width + x] - min) / (max - min) * (maximum - minimum) + minimum;
}
}
}
private static function interpolate(a:Number, b:Number, x:int)
{
var ft:Number = x * 3.1415927;
var f:Number = (1.0 - Math.cos(ft)) * 0.5;
return a * (1.0 - f) + b * f;
}
}