TileMap Scanning?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By slightly_seasoned

I’m following NAD LABS’ tutorial on procedural tile generation, & came across a problem. Sometimes, when I play the scene, all of the tiles are grass tiles, & none of them are water tiles. I thought of scanning the screen & seeing if the amount of water tiles are < insert random integer here, then restart the scene until there’s a reasonable amount of water tiles on the screen. Can anyone tell me how to scan the screen & how to get a tile’s ID?

BTW here’s the code I’m using:

extends Node2D

var width = 60
var height = 34
onready var tile_map = get_node("ProceduralWorldTileMap")
var open_simplex_noise = OpenSimplexNoise.new()

func _ready():
	randomize()
	open_simplex_noise.seed = randi()
	open_simplex_noise.octaves = 5
	_generate_map()

func _generate_map():
	for x in width:
		for y in height:
			var map = floor(abs(open_simplex_noise.get_noise_2d(x, y) * 3))
			tile_map.set_cell(x, y, map)

Sincerely, Some Random Newbie

:bust_in_silhouette: Reply From: timothybrentwood

So what you’re trying to accomplish and the method you’re using to generate a random tile map are conflicting. If you have 1 water tile and 1 grass tile in your TileSet it’s equally likely that you’ll get a grass or a water tile. I would suggest making your map generation function more general first. Then you can add more water tiles to your TileSet to make them have a higher probability of occurring. So if you have 3 water tiles and 1 grass in your TileSet, your code is 3x more likely to select a water tile than a grass tile.

func _generate_map():
    var tile_set = tile_map.tile_set
    var tile_types = tile_set.get_tiles_ids()
    var max_index = tile_types.size() - 1
    for x in width:
        for y in height:
            var map = floor(abs(open_simplex_noise.get_noise_2d(x, y) * max_index))
            tile_map.set_cell(x, y, map)

If you insist on the more brute force method of having a minimum number of water tiles on the map then this will do that but you’ll lose the niceness of the open_simplex_noise generation and the water tiles will look more randomly thrown in there:

func _generate_map():
	var water_tile_index = 2  # whatever the index of your water tile index is
	var water_tiles_generated = []
	var minimum_number_of_water_tiles = 30
	var tile_set = tile_map.tile_set
	var tile_types = tile_set.get_tiles_ids()
	var max_index = tile_types.size() - 1
	for x in width:
		for y in height:
			var map = floor(abs(open_simplex_noise.get_noise_2d(x, y) * max_index))
			tile_map.set_cell(x, y, map)
			if map == water_tile_index:
				water_tiles_generated.append(Vector2(x,y))
			
    while water_tiles_generated.size() < minimum_number_of_water_tiles:
	    randomize()
	    var random_vector = Vector2(randi() % width + 1, randi() % height +1)
	    if random_vector in water_tiles_generated:
		    continue
	    else:
		    tile_map.set_cell(random_vector.x, random_vector.y, water_tile_index)
		    water_tiles_generated.append(random_vector)