Procedural Generation question!

Godot Version

v4.4.1.stable.official [49a5bc7b6]

Question

I want to create an island for my top down gamae, and i need to create it with tilemap terrains, i didn't find any video related to this only procedural generations with just colors like grass is green, water is blue, but i need with my tiles.There is my terrain example.

What exactly is the problem?
It looks like you setup the terrain wrong.
This tutorial shows how to set up the terrain:

I want to create procedural generated island while using terrains, i followed this video https://www.youtube.com/watch?v=rlUzizExe2Q&t=324s to use procedural generation but its just colored tiles, i don’t understand how to use terrains to get smooth transition beetwen grass and sand for example.

You also need to copy her code, which generates the tilemap based on the noise-texture

yes i was using this channels another video to get my bitmask




Idk maybe i made a mistake because its my first time using bitmask also i created tileset myself so maybe thats the problem.

the screenshots look fine to me. Did you also implement the code she presented?

yes, but it was just like in the video there was just colored blockes like green yellow as grass and sand i want smth like this to be generated.


not like this

Can you send your code here?

Sure!

extends Node2D

@onready var tilemap = $map
@export var noise_height_text : NoiseTexture2D

var source_id = 1
var atlas_water = Vector2i(0,3)
var atlas_grass = Vector2i(9,2)
var noise : Noise
var width : int = 200
var height : int = 200
var island_radius = 100

func _ready():
	noise = noise_height_text.noise
	generate_world()
	
func generate_world():
	for x in range(-width/2, width/2):
		for y in range(-height/2, height/2):
			var pos = Vector2(x,y)
			var dist = pos.length()
			var noise_val = noise.get_noise_2d(x * 0.1,y * 0.1)
			var threshold = 0.8
			
			if noise_val + (island_radius - dist) * 0.1 >= threshold:
				tilemap.set_cell(0, Vector2i(x, y), source_id, atlas_grass)
			else:
				tilemap.set_cell(0, Vector2i(x, y), source_id, atlas_water)
				

now this will not work because i swicthed from tilemap to tilemaplayer

Yeah so currently you are only using the “set_cell”-method. You want to use terrains, therefore you need to call set_cells_terrain_connect.

This method takes in an array of cells, so what you want to do is to save the coordinates in a array and then call this method once:

const WATER_THRESHOLD = 0.3
const SAND_THRESHOLD = 0.5

func generate_world():
	var water_cells = []
	var sand_cells = []
	var grass_cells= []
	for x in range(-width/2, width/2):
		for y in range(-height/2, height/2):
			var pos = Vector2(x,y)
			var dist = pos.length()
			var noise_val = noise.get_noise_2d(x * 0.1,y * 0.1)
			
			if noise_val < WATER_THRESHOLD:
				water_cells.append(Vector2i(x, y))
			elif noise_val < SAND_THRESHOLD:
				sand_cells.append(Vector2i(x, y)
			else:
				grass_cells.append(Vector2i(x, y))
	tilemap.set_cells_terrain_connect(water_cells, 0, 2) # Water Cells
	tilemap.set_cells_terrain_connect(sand_cells, 0, 1) # Sand Cells
	tilemap.set_cells_terrain_connect(grass_cells, 0, 0) # Grass Cells

Note that this might cause lag depending on the size of the generation.

You can play around with the threshold to get the kind of generation you want

IMPORTANT: This expects the noise to return a value between 0 and 1. depending on the noise type this can vary

idk what i am doing wrong but it does not generating the world.

extends Node2D

@onready var tilemap = $Ground
@export var noise_height_text : NoiseTexture2D


var noise : Noise
var width : int = 100
var height : int = 100
var island_radius = 50

func _ready():
	noise = noise_height_text.noise
	generate_world()
	
const WATER_THRESHOLD = 0.3
const SAND_THRESHOLD = 0.5

func generate_world():
	var water_cells = [Vector2i(0, 0), Vector2i(1, 0), Vector2i(2, 0)]
	var sand_cells = [Vector2i(0, 0), Vector2i(1, 0), Vector2i(2, 0)]
	var grass_cells= [Vector2i(0, 0), Vector2i(1, 0), Vector2i(2, 0)]
	for x in range(-width/2, width/2):
		for y in range(-height/2, height/2):
			var pos = Vector2(x,y)
			var dist = pos.length()
			var noise_val = noise.get_noise_2d(x * 0.1,y * 0.1)
			
			if noise_val < WATER_THRESHOLD:
				water_cells.append(Vector2i(x, y))
			elif noise_val < SAND_THRESHOLD:
				sand_cells.append(Vector2i(x, y))
			else:
				grass_cells.append(Vector2i(x, y))
	tilemap.set_cells_terrain_connect(water_cells, 0, 3) # Water Cells
	tilemap.set_cells_terrain_connect(sand_cells, 0, 2) # Sand Cells
	tilemap.set_cells_terrain_connect(grass_cells, 0, 1) # Grass Cells

Which noise type are you using?

simplex smooth

Then you have to change the threshold to something like:

const WATER_THRESHOLD = -0.1
const SAND_THRESHOLD = 0.1

Does it throw an error?

nah it openes fine

Hmm okay can you try this code and check the “output” tab to see what gets printed?

extends Node2D

@onready var tilemap = $Ground
@export var noise_height_text : NoiseTexture2D


var noise : Noise
var width : int = 100
var height : int = 100
var island_radius = 50

func _ready():
	noise = noise_height_text.noise
	generate_world()
	
const WATER_THRESHOLD = -0.1
const SAND_THRESHOLD = 0.1

func generate_world():
	var water_cells = []
	var sand_cells = []
	var grass_cells= []
	for x in range(-width/2, width/2):
		for y in range(-height/2, height/2):
			var noise_val = noise.get_noise_2d(x, y)
			
			if noise_val < WATER_THRESHOLD:
				water_cells.append(Vector2i(x, y))
			elif noise_val < SAND_THRESHOLD:
				sand_cells.append(Vector2i(x, y))
			else:
				grass_cells.append(Vector2i(x, y))
	print(water_cells)
	print(sand_cells)
	print(grass_cells)
	tilemap.set_cells_terrain_connect(water_cells, 0, 3) # Water Cells
	tilemap.set_cells_terrain_connect(sand_cells, 0, 2) # Sand Cells
	tilemap.set_cells_terrain_connect(grass_cells, 0, 1) # Grass Cells

it says this ERROR: [output overflow, print less text!]
So i think it being generated but i can’t see, or no ?

okay but this would mean that it should work. The position of the map is (0, 0) right?

yes the tilemaplayer is at 0,0 position.


Actually also i tried smth like this

noise_val = (noise_val + 1.0) * 0.5

and there was just big cube of send with grass outline.

okay try with width = 20 and height = 20 and use simplex smooth again

1 Like