-
Notifications
You must be signed in to change notification settings - Fork 0
6. Generating Randomness
One such algorithm that generates randomness is known as Perlin Noise. Perlin noise can generate various organic effects such as clouds, terrain, and patterned textures. Perlin noise has a more organic appearance (rather than just pure randomness) because it produces a smooth sequence of pseudo-random numbers. In Godot, to use Perlin Noise, you must create a variable of the OpenSimplexNoise class (and initialize the variable) done by:
var noise : OpenSimplexNoise # this declares the var noise as an object of the class OpenSimplexNoise but refrains from giving it a value
noise.seed = randi() # Randomize seed
noise.octaves = 3 # Controls the level of detail (higher values = more detailed noise)
noise.period = 20 # Controls how fast or slow the pattern repeats (higher values = less repetition)
noise.persistence = 0.5 # Controls the intensity of higher frequency noise
Then, to use this, say we want to generate an organic image, with normal random bits this would generally produce harsh contrast, however with Perlin Noise we can create a nice subtle gradient (a slow increase/decrease of RGB values per pixel):
var img = Image.new()
for x in range(256):
for y in range(256):
var value = noise.get_noise_2d(x, y) # Generate a Perlin Noise value at the coordinates (x,y)
var color = Color(value, value, value) # Map the noise to a grayscale value
img.set_pixel(x, y, color)
texture = ImageTexture.new()
texture.create_from_image(img)
In this case, we will talk about the Drunkard's Walk Algorithm where the entity is moving in randomly generated directions up, left, right, or down (because they are drunk). Here is the code to do so (this code is a lot more self explanatory):
var position : Vector2
var steps : int = 1000 # Total number of steps
var step_size : int = 10 # Size of each step
position = Vector2(400, 400) # Starting in the middle of the screen
func draw_walk():
# Drawing the walk on the screen
var random_direction : int
var random_step : Vector2
for i in range(steps):
random_direction = randi_range(0, 3) # Random number between 0 and 3
match random_direction:
0: random_step = Vector2(step_size, 0) # Move right
1: random_step = Vector2(-step_size, 0) # Move left
2: random_step = Vector2(0, step_size) # Move down
3: random_step = Vector2(0, -step_size) # Move up
position += random_step
draw_circle(position, 2, Color(1, 0, 0)) # Red dot for each step
update()
We can use the randi_range(x,y) function where x is an exclusive lower bound and y is an exclusive higher bound. So this means that if x is passed as 1 and y is passed as 5, this function generates a random number between (not including) 1 and 5.