# Write and control Perlin noise for 1D

I'm reading this tutorial and it's the first time I try something this new.

Here is my attempt:

import sys
import math
import pygame
import random

pygame.init()
windowwidth, windowheight = 900, 500
windowsurface = pygame.display.set_mode((windowwidth, windowheight), 0, 32)
clock = pygame.time.Clock()
fps = 30
MAX_INT = (1<<31) - 1
grey = (128, 128, 128)

def linear_interpolate(a, b, x):
return a*(1-x) + b*x

def int_noise(x):
# I'm pretty sure I can use random.uniform(-1, 1) as I need a value in the range (-1, 1)
# I just saw this function on SO that is said to be faster that the build-in.
x = int(x)
x = ((x << 13) & MAX_INT) ^ x
x = ( x * (x * x * 15731 + 789221) + 1376312589 ) & MAX_INT
return 1.0 - x / 1073741824.0

def smooth_noise(x):
return int_noise(x)/2 + int_noise(x-1)/4 + int_noise(x+1)/4

def noise_interpolate(x):
int_x = int(x)
fractional_x = x - int_x

v1 = smooth_noise(int_x)
v2 = smooth_noise(int_x+1)

return linear_interpolate(v1, v2, fractional_x)

def perlin_noise(x):
total = 0
persistence = 1/4
octaves = 10

for i in range(octaves):
frequency = pow(2, i)
amplitude = pow(persistence, i)

total = total + noise_interpolate(x*frequency) * amplitude

#---------------------------------------------------------------------------

def mainloop():
scale = 50
points = [(i, perlin_noise(0.6*i) * scale)
for i in range(0, windowwidth, 10)]
points.append((900, perlin_noise(0.5)))

while True:
clock.tick(fps)
pygame.display.set_caption('fps: %.2f' % clock.get_fps())

# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

# update game state

# draw
for i in range(len(points) - 1):
pygame.draw.line(windowsurface, grey,
(points[i], 350+points[i]),
(points[i+1], 350+points[i+1]), 1)
pygame.display.update()

if __name__ == '__main__':
mainloop()


I know the design is awful, but I'm more concerned if it is the correct way to write all this. From interpolating function, to the smoothing function, all the way to perlin.

I have the feeling that this Perlin noise function is completely wrong and very misleading, regardless the fact that I draw the wave onto the screen.

To begin with, you cannot use random.uniform() in your current design. The tutorial specifically emphasize that the noise function shall be seeded, that is, for the same argument it shall always return the same result.
You can get away with random.uniform() by calculating noise tables (one per octave), and use them as noise functions. In fact, I'd recommend this approach.