Help With Procedural Gen using Tilemaps

WorldSize = 100
Width = 0
Height = 0
DirtLayerHeight = 10

Width = WorldSize / 2
Height = WorldSize / 2
print(Width, Height)


function TerrainGeneration()
	local terrain = {}
	for x = 1, Width do
		terrain[x] = {}
		for y = 1, Height do
			if Height - x < DirtLayerHeight then
				terrain[x][y] = "dirt"
			else
				terrain[x][y] = "stone"
			end
			print("Tile at (" .. x .. ", " .. y .. "): " .. terrain[x][y])
		end
	end
end

TerrainGeneration()

So I need to replace both “dirt” and “stone”, but me being newer to lua and defold I don’t understand how to fetch these from a tilemap, my initial thoughts are to make 2 tilemaps and have them both apart of the GO. But I’m not understanding how the structuring works at all :frowning: . I’ve looked over the tilemap documentation and that doesn’t seem to help me either mainly my lack of understanding does anyone know a good tutorial resource for implementing tilemaps into scripts?

To note: this is just a basic setup I will later use noise to create nil or air tiles for caves and frequencies using a noise generator in 2d much like perlin and pulling a specified value

correct me if i’m misinterpreting what you’re asking, but could the functions tilemap.get_tile and tilemap.set_tile work?
you can view the tile number in the editor in both the tilemap and tilesource. (use 0 for nothing)
though do note that these functions can be a bit slow if called too frequently, so it would be faster to get tiles by storing those in a table instead of calling functions.

i’m also not sure if tilemaps are properly culled yet, so if it’s too big it could bog down performance as well. (workarounds for this, though)

They are not. For a large world you basically only want to draw chunks of it at a time. I have an example of an infinite map here:

DEMO: Infinite Map 0.0
CODE: publicexamples/examples/infinite_map at master · britzl/publicexamples · GitHub

I think some others here on the forum have done similar projects with very large tilemaps.

1 Like

Maybe that demo could be suitable as an example in the dashboard? It comes up now and then how to do something similar and I think it’s a great example

1 Like

Yeah Ik about chunking and culling them I’ve done quite a few proc gen maps using perlin noise where i would i use heights and shallows to create caves, looking now though using tilemaps, I may run into a few problems, the question is pretty layered tbh. Firstly it comes down to whether it’s even possible to use multiple tilemaps and transfer there data ie blocks to a blank one. The reason I would want to do this is because of a block factory think of it like default assignment across multiple different kinds of blocks. Attributes would be Health, Timer, Hardness, and things like that in which each instance of a tile would have an override for any changing variables before being finally stored and cached. I’m just looking for usable methods, mainly right now is figuring out the best way to use multiple tilemaps if that’s not possible I may have to get creative haha.

As for this yeah to an extent however it will only call on a get set function once at the creation of the map after that chunks/culling will handle the rest so it won’t be intensive at all

i would suggest storing block data in a static table and not in a tilemap.
there’s a few way to do it, one such way is this

tileids={["dirt"]=1,["stone"]=2} --for tilemap purposes. might also be useful to create a second table where the indexes are the tile id and the value is the block name

blockdata={ ["dirt"]={health=4,hardness=0}
["stone"]={health=6,hardness=1}}

another way would be to do this

blockdata={ --uses numerical indexes, would also have to store the world data in numbers
[1]={=blockname="dirt",health=4,hardness=0}
[2]={blockname="stone",health=6,hardness=1}
} --these number-indexes are redundant to put, as they are already implicit, but it makes it easier to read.

each option has its benefits and drawbacks.
the first option is marginally easier to read, and allows you to add or remove tiles more or less at will without risking corrupting save files or other unwanted effects of removing or adding content
the second option is faster in terms of computational time, and would result in save data using less space (if that’s a particular concern), and adding new blocks would be easier since it’s all on one table, though you would have to make sure that the tile id matches the index of the block

as for individual tile data, i would suggest using a table to store that.
terrain[4][5]={} --put relevant data here

2 Likes

Yeah for the most part that’s pretty much what I’m going for the only "individual data types I need to track is health and a timer component I planned on placing a global timer component on the player so when he loads a previous unloaded chunk time is accelerated on that chunk to adjust to the proper time. In other words if he’s farming and comes back after a while the plants have grown giving the appearance that it was loading the whole time