2D Terrain Generator

2D Terrain Generation using Perlin noise!

by synoooot

Author Avatar

Terrain is integral to a game; it's what you play on, walk on, explore on, and so on. And oftentimes, making it is hard, and you can't make it infinite. But, if you were to automatically generate it, theoretically it'll be infinite. So, how do you do it?

Part 1: Generating Noise

Noise is integral to a terrain generator. Whether it be random, sporadic numbers, or a methodical kind of noise e.g. Perlin Noise, you need it to make a generator. Our only good source of noise is Perlin noise so we're going to be using that.

Simply, all we need to do is make a for loop that goes through our entire mapsize and get the noise value for that x, y coordinate and then we're basically done with our basic, but very nice looking terrain!

So, the first step is getting the noise. Simple!

for x = 0, mapsize do
    for y = 0, mapsize do
        local height = math.noise(x, y, seed)

You may see that math.noise is 3D perlin noise - it takes in an X, Y, and Z value. Which isn't very useful in our case since we're not going to use 3D perlin noise, so we can substitute the Z value with any number you want.

Part 2: Visualizing It

Now we get into the fun part. Tuning and putting our noise into the wild, wild world!

The next step in world glory of making terrain is smoothing & amplifying it.

math.noise(x / 50 or 0, y / 50 or 0, seed) * 20

That's the function I use to make my perlin noise. Now, why do we divide the numbers? The resulting noise is very smooth and not very jagged, at all. And why do we multiply it? Perlin noise often returns a value somewhere between 0 and 1. No higher, but sometimes lower (it's range is -1 to 1).

So, by multiplying it, we get a higher number. Be careful when multiplying by higher numbers, they can make your terrain look ugly.

And by dividing it, we make hills less frequent/more spread out. However, if you divide it by a lower number, the hills become more intense and compacted together.

Now to place down parts with our noise!

for x = 0, mapsize do
    for y = 0, mapsize do
        local h = math.noise(x / 50 or 0, y / 50 or 0, seed) * 20
        local p = Instance.new("Part")
        p.Position = Vector3.new(x * size, h, y * size)
        p.Anchored = true
        p.Size = Vector3.new(size, size, size)
        p.Parent = workspace

That's the whole script for making the noise! Here's an explanation: Every time x increments by 1, another y loop starts. While y is running, it gets the noise of x, y, and seed (smoothed and amplified) and creates a part the next line. The X and Y are multiplied by the size to make sure no parts overlap. And then we anchor it, and set it's size. Then we set it's parent to workspace.

Tada! Rolling hills full of gray brick goodness!

I hope you enjoyed and/or learned from this tutorial!

Here are a few pro-tips and ideas: In the X loop, after "for y[...] end" put a line with "game:GetService("RunService").Heartbeat:Wait()" so it doesn't lag your computer as hard

You can round the height, and if you wanna go for the voxel aesthetic, such as Minecraft, you can round it and multiply it by your block size.

You can (and should) set a water level and make the height, if it's below the water level, equal to the water level. (e.g. the water level is 0, the height is -1, so it gets set to 0). This makes it look like islands in the water or something, which is what I made using this!

Here's an example of something that could be made using this terrain generator:


(All of this was automatically generated using the same formula, except the height was rounded and multiplied by the block size.)

Have a good day.

View in-game to comment, award, and more!