Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How modify Perlin Noise [see example in thread]

I'm use Perlin Noise for world generator in 2D (how in Terraria). I found an implementation that suits me. I need to generate parts of the world, but this realization can only generate once the whole world.

Realization - http://sirisian.com/javascriptgame/tests/valuenoise2.html I rewrote it to AS3, slightly modifying (+ main code) - http://codepad.org/crMEQ2DD

Please help to modify the code so that it was possible to generate a noise part:

PerlinNoise.randomize(65735);
...
var noises:Vector.<Number> = PerlinNoise.getNoise(0, 0, 100, 100, 6, 6, 1.0, 20);
...
var noises:Vector.<Number> = PerlinNoise.getNoise(100 /*<--x offset*/, 0, 100, 100, 6, 6, 1.0, 20);

I tried several options, but the different noise parts are not docked.

And if you have an implementation of Perlin Noise, which is suitable for the world generator, you can give it to me.

Thanks!

like image 704
FailMan Avatar asked Nov 04 '22 22:11

FailMan


1 Answers

Flash already contains an implementation of Perlin noise, through the BitmapData.perlinNoise() method. What you can do if you need to get the noise as a vector of numbers (as opposed to a renderable bitmap) is to then use the BitmapData.getVector() method which returns all the pixels as a vector of 32 bit integers, where the four bytes represent alpha, red, green and blue channels respectively.

I've employed this very pattern in a project myself, to great success. Below is the very function I wrote and used.

public static function initNoiseVector(output : Vector.<Number>, baseX : Number, numOctaves : Number, scale : Number, blur : uint = 0) : void
{
    var i : uint;
    var len : uint;
    var sum : uint;
    var avg : uint;
    var perlin : BitmapData;
    var noise : Vector.<uint>;

    len = output.length;

    perlin = new BitmapData(len, 1);
    perlin.perlinNoise(baseX, 1, numOctaves, 0, true, false, 7, true);

    if (blur > 0)
        perlin.applyFilter(perlin, perlin.rect, new Point(), new BlurFilter(blur, 1, 3));

    noise = perlin.getVector(perlin.rect);

    // Calculate average
    sum = 0;
    for (i=0; i<len; i++) {
        // Mask out blue channel
        sum += noise[i]&0xff;
    }
    avg = sum/len;

    for (i=0; i<len; i++) {
        var speed : Number;

        // Convert perlin noise color to value between -1 and 1
        speed = ((noise[i]&0xff) - avg) / avg;
        output[i] = speed * scale;
    }
}

This function basically just creates a 1px high bitmap (width defined as the length of the vector), initiates grayscale Perlin noise in that bitmap, optionally applies a blur and then scales the values according to the scale function argument.

The scaling is done by first calculating the average value (using just the blue channel, since all channels will be identical due to the noise being grayscale.) The values are then normalized between -1 and 1, where the average will be 0, and scaled by the supplied scale factor.

The function can then be used in the following way, to retrieve 1000 values:

_noise = new Vector.<Number>(1000, true);
PerlinNoiseUtil.initNoiseVector(_noise, 300, 10, randomDev * periodTime, 10);

Hope this helps!

like image 147
richardolsson Avatar answered Dec 13 '22 22:12

richardolsson