# Smooth 1D terrain generation

So I'm pretty happy with my terrain, and the progress on my game. I just want to figure out why the terrain is so steep sometimes. Right now to generate my random seed I use this:

seed = (long)(Math.random() * 10000000 + 12345670);


It works, but some of the seeds just make a really steep point hill, while I'm looking for more bumpy-flat maps (similar to Terraria's).

Here's my create terrain loop:

for (int i = minX; i < maxX; i++) {
int columnHeight = p.getNoise(i, maxY);
for (int j = 0; j < columnHeight; j++) {
System.out.println(columnHeight);
map[i][j] = new Tile(i * 8, j * 8, 8, 8, TileType.Grass);
}
}


Here's the class I'm using to try to generate terrain. I tried tweaking parameters but nothing works, and I just keep getting crazy random hills.

public class Perlin {
private long seed;

// Constructor to create a seed
public Perlin(long seed){
this.seed = seed;
}

// Fetches a random value
private int random(int x, int range){
return (int) ((x + seed) * (x + seed) * 8) % range;
// o = (int) (((x + seed)*(x + seed))*5) % range
//return o;
}

// Calculates the noise
public int getNoise(int x, int range){
int chunkSize = 64;

int chunkIndex = x  / chunkSize;

float prog = (x % chunkSize) / (chunkSize * 1f);

float left_random = random(chunkIndex, range);
float right_random = random(chunkIndex + 1, range);

float noise = (1 - prog) * left_random + prog * right_random;

return Math.round(noise);
}
}


Here's a picture of the terrain compared to what I want (what I want is in red):

EDIT So I understand what you guys mean about the previous Perlin class not actually being perlin noise. I fixed it with some tweaking and using actual perlin noise, the only thing I'm partially confused about is the seeds, and how do they work..

for example in Java this is how they do it

x = (x<<13) ^ x;
return (float)( 1.0 - (( (x * (x * x * 1376312589 + 789221) + 1376312589) + 3517) & Integer.MAX_VALUE) / 2543768824f);


if someone could explain what all that really means it'd be great, and why does it use prime numbers?

• If the green is terrain, that doesn't look random at all. It's a straight line up, then a straight line down. Is that a representative output? – Anko Oct 24 '15 at 0:11
• I'd recommend finding a Perlin/Simplex/OpenSimplex library and using that instead of using the noise class you wrote yourself. You call it "Perlin" but it's not Perlin noise. You pick two random heights and linearly interpolate between them. Linear interpolation will give you straight lines. – amitp Oct 24 '15 at 0:17
• I also don't get what is random in the picture. I didn't get what exactly you mean by 1D too. Would it mean that you are interested only in the height of a 2D mountain, perhaps? – MAnd Oct 24 '15 at 0:45
• @Anko yeah.... that probably wasn't the best screenshot but it does just basically go up and down, but sometimes creates a smoother hill, I just don't know why they're so steep – Seeocon Oct 24 '15 at 2:08
• @hzyy There's very few people, who can actually write perlin noise themselfs. – Bálint Apr 7 '16 at 11:51

I didn't get the entire gist of all the functions you provided, but it seems to me that you are looking for something like a random walk or martingale algorithm, where you have an equal probability of the terrain height step to go up or down in comparison to the terrain one step ago. Doing this, your terrain remains random but essentially smooth and without crazy drops and most likely mean level in the long run.To illustrate, try something like this :

int posneg = rand() % 17 + (-8);
height[i+1]=height[i] + posneg;


You should obtain a height terrain similar to the requested red line.

You can tweak the line with a deterministic trend within a longer range, ensuring that there is a mountain building up or a dale for some while.

height[i+1]=height[i] + posneg + trend;


Where trend is a random number between - 4 and 4 that remains constant for, let's say, 50 iterations of i. You may wish also to have int(50/aPower) iterations and pow(trend, aPower), where aPower is a random number 1, 2 or 3 to have the mountains a bit less boring and occasionally very steep. And finally, you may play with going an iteration back for a few steps by a small random chance to have an overhang.

the steps to do this are:

• generate a list of N random heights int h[];
• generate a list of N-1 distances where distance is the difference between the 2 heights dist=abs(h[i] - h[1])
• use this information do draw your line segments with the desired amount of noise where the number of segments between points is <= distance.

this will ensure that the average change in height is constant. experiment with adding a small amount of randomness to the list created in step 2.

Just for the record, here you can check the original Perlin docs, where everything is greatly explained. Basically perlin points are generated and interpolation is done between them. The spacing between points will state the terrain's rugosity.

The seed determines the specific output of your noise algorithm for each particular number, but does not determine the "phenotype" of your terrain, which is the general way it looks accross all possible seeds.

That look depends on the noise generation algorithm itself - frequency, octaves, amplitude and the smoothing. The seed doesn't have anything to do with it. Look into the various tutorial on Perlin and Simplex noise (complicated), value noise (simple) or other techniques. They will all have a section about the different variables in the noise generation formula and how they affect the outcome.