• 10
• 9
• 12
• 14
• 13

# Need advice/help with simple noise functions and 2D terrain gen

This topic is 651 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm following this article in order to understand noise algorithms, and I'm still only half way through it, so I'm still doing the simpler stuff. As I'm doing this I'm trying to translate what I learn into my intended application of it: terrain generation for a platformer (I can't find any useful tutorials for this...). However, I don't know if I'm doing this right, and there's also a few things I'm getting confused about.

I figured if I got the output values of the noise functions between 0 and 1, and then multiply that output by the height of the map (which is for now the same size as the screen (768px)), it could work. I can use that to know where each tile goes. I figured if I later have a bigger map I can lower this value to something sensible like, say, a 5th of the map's height.

Am I on the right track here? It does seem to work. Kind of...

The results from the red noise function are quite appealing (with 50 smoothing passes).

But the results from the violet one always go near the top of the screen/map and I don't know if that's natural behavior or a flaw in what I'm doing. I figure it's the latter since I'm not being able to display them any lower by playing with the numbers.

The tiles at the bottom are actually wrapping around the top cells, which is why the red lines aren't connecting to them.

I'm also confused about whether the output should include negative values (-1 to 1). The article author uses them here and there without even flinching. But I'm not sure how to account for that. I'm not using any, but the rough() function (below) naturally gives me some. If I converted those negative values to positive, I end up taming the violet function, but only slightly. And the tiles are still near the top.

Here are the functions as I made them (in python (pySFML)):

# In the Noise class...
# I stripped these functions of class specific stuff,
# like 'self.' and '@classmethod', for readability

def red(n, seed = 0, lmin = 0, lmax = 99, avg = 0.5, passes = 1):
random.seed(seed)
points = []

for i in xrange(n):
points.append(random.randint(lmin, lmax)*0.01)

# smooths the values
return smooth(points, avg, passes)

def violet(n, seed = 0, lmin = 0, lmax = 99, avg = 0.5, passes = 1):
random.seed(seed)
points = []

for i in xrange(n):
points.append(random.randint(lmin, lmax)*0.01)

# roughs the values
return rough(points, avg, passes)

def smooth(noise, avg, passes):
if passes > 0:
output = []

for i in xrange(len(noise)):
if i is not len(noise)-1:
output.append( avg * (noise[i] + noise[i+1]) )
else:
# Average of the last value and the first
output.append( avg * (noise[i] + noise[0]) )

return smooth(output, avg, passes-1)
else: return noise

def rough(noise, avg, passes):
if passes > 0:
output = []

for i in xrange(len(noise)):
if i is not len(noise)-1:
output.append( avg * (noise[i] - noise[i+1]) )
else:
# Diference between the last value and the first
output.append( avg * (noise[i] - noise[0]) )

return s.rough(output, avg, passes-1)
else: return noise

# and in the World class
# I use 's.' instead of 'self.', by the way

def genNoise(s):
numPoints = s.numCellsX*s.tsize                 # s.tsize = tile size (16px)
s.points = Noise.red    (numPoints, 0, 0, 100, 0.5, 50)
# s.points = Noise.violet(numPoints, 0,  0, 100, 0.5, 3)

def placeTiles(s):
for i in xrange(len(s.points)):
p = s.points[i]

tileX = int(i%s.csize)                     # s.csize = cell size (16 tiles)
tileY = int(((p*s.mh)/s.tsize)%s.csize)    # s.mw/s.mh = map width/height (1280x768)
cellX = int((i%s.mw)/s.csize)
cellY = int(((p*s.mh)/s.tsize)/s.csize)

s.cells[cellX][cellY].tiles[tileX][tileY].show()
s.cells[cellX][cellY].hasTiles = True


Edited by Master Thief