Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does this JavaScript code follow the Midpoint Displacement algorithm?

I'm trying to use the Midpoint Displacement Algorithm using JavaScript and canvas as recommended on gamedev.stackexchange.com.

The code below generates points where the array index is the x position and its value is the y position.

var createTerrain = function(chops, range) {
    chops = chops || 2;
    range = parseInt(range || 100); 

    if (chops > 8) return;

    var cycle = parseInt(width / chops);    

    for (var i = 0; i <= width; i += cycle) {

        var y = (height / 2) + getRandomNumber(-range, range);

        terrain[i] = y;

    }

    chops *= 2;
    range *= 0.5;
    createTerrain(chops, range);

}

getRandomNumber()'s arguments are min and max. width and height are respective of the canvas.

This produces something like... Canvas

It seems pretty choppy, but that may just be how it is.

Have I got this algorithm right? If not, what is wrong, and can you point me in the right direction?

like image 955
alex Avatar asked Mar 07 '11 15:03

alex


1 Answers

I'd say it does not look like mid-point displacement, simply because every segment should be getting a regular X axis length (you have nearly vertical segments). Have you tried to generate a simple 4-segment array? What does it look like?

Here is a short tutorial I wrote, you can see it in action: Mid-point algorithm in Javascript

The source code:

function Terrain(segmentCount) {
    this.segmentCount = segmentCount;
    this.points = [];
    for (i=0; i<=segmentCount; ++i) {
        this.points[i] = 0;
    }
};

/**
* Generate the terrain using the mid-point displacement algorithm. This is in fact
* a shortcut to the recursive function with the appropriate value to start
* generating the terrain.
*
* @param maxElevation the maximal vertical displacement to apply at this iteration
* @param sharpness how much to attenuate maxElevation at each iteration (lower
*        value means a smoother terrain). Keep between 0 and 1.
*/
Terrain.prototype.generateUsingMidPoint = function(maxElevation, sharpness) {
    this.midPoint(0, this.segmentCount, maxElevation, sharpness);
}

/**
* This is the recursive function to actually generate the terrain. It computes a new height for the point
* between "start" and "end" (the mid-point): averages start and end heights and adds a random
* displacement.
*
* @param maxElevation the maximal vertical displacement to apply at this iteration
* @param sharpness how much to attenuate maxElevation at each iteration (lower
*        value means a smoother terrain). Keep between 0 and 1.
*/
Terrain.prototype.midPoint = function(start, end, maxElevation, sharpness) {
    var middle = Math.round((start + end) * 0.5);
    if ((end-start<=1) || middle==start || middle==end) {
        return;
    }

    var newAltitude = 0.5 * (this.points[end] + this.points[start]) + maxElevation*(1 - 2*Math.random());
    this.points[middle] = newAltitude;

    this.midPoint(start, middle, maxElevation*sharpness, sharpness);
    this.midPoint(middle, end, maxElevation*sharpness, sharpness);
};
like image 127
Vincent Mimoun-Prat Avatar answered Nov 07 '22 11:11

Vincent Mimoun-Prat