@@slothinahat I just understood the question, sorry xd. I would like to learn everything you have done in that project: 3 inventory, collect items, enemies, generation of dungeons etc n.n
Great tutorial ! I used it to learn Godot to make a random island generator for my dnd campaign. I would love to see other tutorial on random generation ! If I can make a critic, this video was a bit quick compared to the first one, you took let loss time explaining what is happening, making it a bit harder to follow. Thank you again for your tutorials !
yeah, I was kind of in a hurry to make the second part, since a lot of people were asking where it was. If you have any other questions you can just ask in the comments.
@@slothinahat Yeah i can imagine it's some pressure when people ask you to make another video in a short delay. Don't worry it was very useful anyway :) I made my own version of the code from what i learned in your video, but i'm a newbie in coding and godot, so my code is quite dirty. I had a hard time figuring how to make an island (i mean, a central one sourrounded by sea, not jut raising the water lelvel for a heightmap), but i found a way (thank to another godot video) with a CustomGradientTexture making a radial gradient (addon), that i substract from the OpenSimplexNoise... Now i search a way to "combine" different gradients so i can obtain other forms than a round island, like a long one or two small ones (i only use altitude for the moment for the biome, i'll add moisture and temp later)... but for the moment i did'nt found a solution : if i use a first radial gradient the size of the picture to "islandize" the terrain it is ok, when i try to combine this radial gradient with a second smaller radial gradient, as this one is smaller thant the size of the picture, i make harsh lines where it intersect with the first radial gradient (i suppose when it is "outer limits" it return null instead of a value..)... Well sorry you dont have to answer this loooong "question" lol. I'll probably figure it in a few days...
@@TheMrDoliprane if you search up something like falloff map or fall off gradient you should find what you are looking for. here is a good explanation of the concept not in Godot though ruclips.net/video/COmtTyLCd6I/видео.html but basically you subtract larger and larger values from alt(pos) the farther away you are from the center.
@@slothinahat Thank you I'll watch it... I just have to find how to make a "for i in x: / for j in y:" loop to come from the center to the outside instead of lines and columns ^^
@@TheMrDoliprane if you know the coordinates of the center tile by dividing the width/2 and the height/2 you can still loop in rows and columns and just check the center coords - current coords to get the distance form the center for each tile.
If anybody is having problems with certain blocks not creating. do this i had it so 5 block types exits. func set_tile(width, height): for x in width: for y in height: var pos = Vector2(x, y) var alt = altitude[pos] var temp = temperature[pos] var moist = moisture[pos]
#Ocean if between(alt, 0, 0.15): tilemap.set_cellv(pos, 4) else: #Snow if between(moist, 0, 0.1): tilemap.set_cellv(pos, 3) #Plains if between(moist, 0.1, 0.5): tilemap.set_cellv(pos, 1) #Desert if between(moist, 0.5, 0.75): tilemap.set_cellv(pos, 2) #Jungle if between(moist, 0.75, 1): tilemap.set_cellv(pos, 0) the jungle block wouldnt generate right. func set_tile(width, height): for x in width: for y in height: var pos = Vector2(x, y) var alt = altitude[pos] var temp = temperature[pos] var moist = moisture[pos]
#Ocean if between(alt, 0, 0.15): tilemap.set_cellv(pos, 4) else: #Snow if between(moist, 0, 0.1): tilemap.set_cellv(pos, 3) #Plains if between(moist, 0.1, 0.5): tilemap.set_cellv(pos, 1) #Desert if between(moist, 0.5, 0.75): tilemap.set_cellv(pos, 2) #Jungle if moist > 0.75 : tilemap.set_cellv(pos, 0) doing this fixed it for me
important thing: if you want random worlds on startup that are different each time you need a variable, that's equal to RandomNumberGenerator.new(), then in generate map, do variable.randomize() and finally you can set OpenSimplexNoise to variable.randi()
@@slothinahat hey, i have a player script with movement and all, located in generate map scene. how do i make it so that the trees layer ontop of the player instead of under them?
@@IndieIndite If it is in a top down/ 3/4 perspective just put the player as a child of a y sort along with making sure that you are instancing the trees to the same y sort.
@@slothinahat you should definitely update this tutorial for godot 4, as some things have changed: like open simplex noise being replaced with fast noise lite, the ysort node being removed in favor of a simple parameter, and also how to make this tile infinitely, but without exploding my pc!
I would recommend selecting random tiles and then checking the biome at that position to decide what structure to place. After which you could call a function that places tiles around that point to make the structure
Luckily for you someone just made a tutorial on exactly this. All of the code you are looking for is in their process function at the very bottom. ruclips.net/video/4b5JGDf43Cg/видео.html
So the simplest way I found was. You make an extra file, that is gone be saving all the data. Then have it somewhat like the following: ---- Start File ---- extends Resource class_name WorldData export var temperature = {} export var altitude = {} export var moisture = {} export var seedValue = 0 func _init(temp, alt, moi, seedVal): temperature = temp altitude = alt moisture = moi seedValue = seedVal ---- End File ---- Then to use it, its usefull to have the following function ---- Start Function ---- func load_data(file_name): if ResourceLoader.exists(file_name): var data = ResourceLoader.load(file_name) if data is WorldData: return data return null ---- End Function ---- This is to load it. To save it ---- Start Function ---- ResourceLoader.save(file_name, Resource) ---- End Function ---- To make the resource: [class_name].new([array of values you want to save])
@@ScorpioneOrzion Yes, this would save all of the biomes, but the randomized parts of the terrain such as trees and grass patches would need additional variables to store, so you would still have to keep track of each of the tiles in a dictionary.
@@slothinahat Tho the way I save it I could just only save the seed, and for the rest, the 3 numbers you get from alitude, temperature and moisture can be resused to get even more numbers, say you multiply all by 1000, then take the first 3 fractional numbers, and do it again, for a total of 6 numbers. So say one is 0.123456789, you would get the numbers 456 and 789.
sorry shouldve clarified more. the world has trees generating but only in the part the player can see when the game starts. so when the player moves theres no more trees.
It could be the world size you set in the beginning of the program being smaller than your actual world size, if not that try enabling collision shapes and seeing if they are under some layer
@@slothinahat yup the world size is huge. like 30x30 monitors i guess you could say it like that how would i make it so the world is smalled when starting up so the game will work proprelly? soz if im asking alot
If i have a tree that can be random sorta like the way terraria trees are generated where the tree is split up into 16x16 pieces for the trunk would it work? for it to grow and work?
I don’t think the trees growth cycle has anything to do with the terrain generation system. As long as you are instancing an object that has all of the growth logic in it it should work fine
@@synapse5791 For the tilemap, I'm pretty sure godot automatically decides what to render, but for nodes I think you have to do it yourself. The visibility modifier node only renders things that are on screen, which may help.
@@slothinahat yeah i was looking into it a bit and people said if you dont want to use arrays (i dont know how to lolz) you can just make it so it only runs the code if its visible and the rest is stored in ram. (like 5 - 10 kb per node)
@@slothinahat also how would you go about saving the scene? would you just serialize the entire scene and add a variable for when its generating and make it only generate if that variable is equal to zero or something like that then when its done generating do you like change it to one then serialize the scene to save everything?
Most of the time taken is from instancing all of the trees and other nodes. To fix this the easiest method is to generate the map in smaller chunks at a time.
@@slothinahat I was thinking that was the case. But I am unfamiliar with chunk loading/saving. Although I don't know if deleting/reloading would even be a problem on 2D since it wouldn't take much to keep what's generated up at all times unlike games like Minecraft. All this aside great tutorial! This was much shorter and more efficient coverage than a lol of the other videos on the topic.
@@OnlySamCan That is true, however the problem lies with all of the nodes being instanced and you will start to see frame drops whenever a chunk is generated.
can i implement the animal scripts from your main game into my game? i managed to spawn in moving animals for my game with your code, just asking for permission to keep the feature.
Why don't you say p-ah-s for pos instead of pose? The pos variable is short for position so calling it pose sounds weird like you don't know what it stands for
an error occurred :, v, I'm at the end of the tutorial 4:45, and this error appears: Invalid get index of type "String" (on base: "Dictionary"). and send me here: var instance = objetos_de_bioma[str(random_object)].instance()
It may be because the biome or object name you provided was spelled differently in the tiles/object tiles dictionary. Try to check that all of the spellings for the names match
Sorry for the delay, I got busy with the GMTK game jam
Git Hub: github.com/SlothInTheHat/godot_terrain_generation
300 today?
part 3? uwu
Is there something in particular you want?
@@slothinahat hmm yes maybe? I don't know xD i just will continue the tutorial uwu
@@slothinahat I just understood the question, sorry xd. I would like to learn everything you have done in that project: 3 inventory, collect items, enemies, generation of dungeons etc n.n
A lot of that stuff like inventory system and enemies can be found on heart beast’s channel, which is where I learned how to do it from
Great tutorial ! I used it to learn Godot to make a random island generator for my dnd campaign. I would love to see other tutorial on random generation ! If I can make a critic, this video was a bit quick compared to the first one, you took let loss time explaining what is happening, making it a bit harder to follow. Thank you again for your tutorials !
yeah, I was kind of in a hurry to make the second part, since a lot of people were asking where it was. If you have any other questions you can just ask in the comments.
@@slothinahat Yeah i can imagine it's some pressure when people ask you to make another video in a short delay. Don't worry it was very useful anyway :) I made my own version of the code from what i learned in your video, but i'm a newbie in coding and godot, so my code is quite dirty. I had a hard time figuring how to make an island (i mean, a central one sourrounded by sea, not jut raising the water lelvel for a heightmap), but i found a way (thank to another godot video) with a CustomGradientTexture making a radial gradient (addon), that i substract from the OpenSimplexNoise... Now i search a way to "combine" different gradients so i can obtain other forms than a round island, like a long one or two small ones (i only use altitude for the moment for the biome, i'll add moisture and temp later)... but for the moment i did'nt found a solution : if i use a first radial gradient the size of the picture to "islandize" the terrain it is ok, when i try to combine this radial gradient with a second smaller radial gradient, as this one is smaller thant the size of the picture, i make harsh lines where it intersect with the first radial gradient (i suppose when it is "outer limits" it return null instead of a value..)... Well sorry you dont have to answer this loooong "question" lol. I'll probably figure it in a few days...
@@TheMrDoliprane if you search up something like falloff map or fall off gradient you should find what you are looking for.
here is a good explanation of the concept not in Godot though ruclips.net/video/COmtTyLCd6I/видео.html
but basically you subtract larger and larger values from alt(pos) the farther away you are from the center.
@@slothinahat Thank you I'll watch it... I just have to find how to make a "for i in x: / for j in y:" loop to come from the center to the outside instead of lines and columns ^^
@@TheMrDoliprane if you know the coordinates of the center tile by dividing the width/2 and the height/2 you can still loop in rows and columns and just check the center coords - current coords to get the distance form the center for each tile.
Would be great to see a part 3 !
I will watch your career with great interest
But seriously tho great tutorial
Thanks!
If anybody is having problems with certain blocks not creating. do this
i had it so 5 block types exits.
func set_tile(width, height):
for x in width:
for y in height:
var pos = Vector2(x, y)
var alt = altitude[pos]
var temp = temperature[pos]
var moist = moisture[pos]
#Ocean
if between(alt, 0, 0.15):
tilemap.set_cellv(pos, 4)
else:
#Snow
if between(moist, 0, 0.1):
tilemap.set_cellv(pos, 3)
#Plains
if between(moist, 0.1, 0.5):
tilemap.set_cellv(pos, 1)
#Desert
if between(moist, 0.5, 0.75):
tilemap.set_cellv(pos, 2)
#Jungle
if between(moist, 0.75, 1):
tilemap.set_cellv(pos, 0)
the jungle block wouldnt generate right.
func set_tile(width, height):
for x in width:
for y in height:
var pos = Vector2(x, y)
var alt = altitude[pos]
var temp = temperature[pos]
var moist = moisture[pos]
#Ocean
if between(alt, 0, 0.15):
tilemap.set_cellv(pos, 4)
else:
#Snow
if between(moist, 0, 0.1):
tilemap.set_cellv(pos, 3)
#Plains
if between(moist, 0.1, 0.5):
tilemap.set_cellv(pos, 1)
#Desert
if between(moist, 0.5, 0.75):
tilemap.set_cellv(pos, 2)
#Jungle
if moist > 0.75 :
tilemap.set_cellv(pos, 0)
doing this fixed it for me
Oh my goodness ,thank you!
Very nice tutorial, thz
You should post these in the Godot tutorials discord channel for more discoverablility
Great video! However, the github is missing the Tree and Cactus graphic files and Scenes.
Will you make a video about generating objects in certain biomes, as you did in part 2 of the Godot 3 tutorial?
important thing: if you want random worlds on startup that are different each time you need a variable, that's equal to RandomNumberGenerator.new(), then in generate map, do variable.randomize() and finally you can set OpenSimplexNoise to variable.randi()
yep, I just like to call the randomize function in the ready and it seems to do the trick.
@@slothinahat hey, i have a player script with movement and all, located in generate map scene. how do i make it so that the trees layer ontop of the player instead of under them?
@@IndieIndite If it is in a top down/ 3/4 perspective just put the player as a child of a y sort along with making sure that you are instancing the trees to the same y sort.
Thanks for the tip, was helpful. Knew I was not crazy when the previous method kept resulting in the same generated layouts, lol.
Excellent tutorial!
Will there be more videos from this topic?
I’m not quite sure yet. If I decide to add on to it then I will definitely make more tutorials.
@@slothinahat you should definitely update this tutorial for godot 4, as some things have changed:
like open simplex noise being replaced with fast noise lite,
the ysort node being removed in favor of a simple parameter,
and also how to make this tile infinitely, but without exploding my pc!
hey! what about multi-tile structures, like small loot rooms? thanks for the tutorials!
I would recommend selecting random tiles and then checking the biome at that position to decide what structure to place. After which you could call a function that places tiles around that point to make the structure
you are the best, i still saying the same uwuwuwu
can you show us how to make infinite optimized worlds using this?
Luckily for you someone just made a tutorial on exactly this. All of the code you are looking for is in their process function at the very bottom. ruclips.net/video/4b5JGDf43Cg/видео.html
@sloth in a hat Thank you so much, I was about to cry because I couldn't figure it out😀
visit my channel , there is a video about that , leave a comment if u want to ask something
@@slothinahat This video is unavailable ;(
But how to save and load it as map of player. Thank you for this.
I would create a dictionary of each tile along with the position and save it as a json inn a text file
So the simplest way I found was.
You make an extra file, that is gone be saving all the data.
Then have it somewhat like the following:
---- Start File ----
extends Resource
class_name WorldData
export var temperature = {}
export var altitude = {}
export var moisture = {}
export var seedValue = 0
func _init(temp, alt, moi, seedVal):
temperature = temp
altitude = alt
moisture = moi
seedValue = seedVal
---- End File ----
Then to use it, its usefull to have the following function
---- Start Function ----
func load_data(file_name):
if ResourceLoader.exists(file_name):
var data = ResourceLoader.load(file_name)
if data is WorldData:
return data
return null
---- End Function ----
This is to load it.
To save it
---- Start Function ----
ResourceLoader.save(file_name, Resource)
---- End Function ----
To make the resource:
[class_name].new([array of values you want to save])
@@ScorpioneOrzion Yes, this would save all of the biomes, but the randomized parts of the terrain such as trees and grass patches would need additional variables to store, so you would still have to keep track of each of the tiles in a dictionary.
@@slothinahat Tho the way I save it I could just only save the seed, and for the rest, the 3 numbers you get from alitude, temperature and moisture can be resused to get even more numbers, say you multiply all by 1000, then take the first 3 fractional numbers, and do it again, for a total of 6 numbers. So say one is 0.123456789, you would get the numbers 456 and 789.
Hey I want to use this concept for making a strategy map like SPAZ 2 or CK im hoping you can lead me in the right direction
ive got a issue where it works but only in the visible parts of the game.
any clue on how to fix it?
sorry shouldve clarified more. the world has trees generating but only in the part the player can see when the game starts. so when the player moves theres no more trees.
It could be the world size you set in the beginning of the program being smaller than your actual world size, if not that try enabling collision shapes and seeing if they are under some layer
@@slothinahat yup the world size is huge. like 30x30 monitors i guess you could say it like that how would i make it so the world is smalled when starting up so the game will work proprelly? soz if im asking alot
i think i will make the players camera zoomed in maybe that would work
I will try do something like making a tilemap for the trees and stones etc and then when in view the trees and stuff get instanced to real trees
If i have a tree that can be random sorta like the way terraria trees are generated where the tree is split up into 16x16 pieces for the trunk would it work? for it to grow and work?
I don’t think the trees growth cycle has anything to do with the terrain generation system. As long as you are instancing an object that has all of the growth logic in it it should work fine
@@slothinahat oh nvm i forgot godot has a frustum culling feature so i assume chunks wont be needed for a game like this? or am i wrong
@@synapse5791 For the tilemap, I'm pretty sure godot automatically decides what to render, but for nodes I think you have to do it yourself. The visibility modifier node only renders things that are on screen, which may help.
@@slothinahat yeah i was looking into it a bit and people said if you dont want to use arrays (i dont know how to lolz) you can just make it so it only runs the code if its visible and the rest is stored in ram. (like 5 - 10 kb per node)
@@slothinahat also how would you go about saving the scene? would you just serialize the entire scene and add a variable for when its generating and make it only generate if that variable is equal to zero or something like that then when its done generating do you like change it to one then serialize the scene to save everything?
💖💖💖💖💖
How do you suggest making this faster? At larger sizes this method takes for ever to generate?
Most of the time taken is from instancing all of the trees and other nodes. To fix this the easiest method is to generate the map in smaller chunks at a time.
@@slothinahat I was thinking that was the case. But I am unfamiliar with chunk loading/saving. Although I don't know if deleting/reloading would even be a problem on 2D since it wouldn't take much to keep what's generated up at all times unlike games like Minecraft. All this aside great tutorial! This was much shorter and more efficient coverage than a lol of the other videos on the topic.
@@slothinahat hey how we made tree and cactus nodes i tried but not worked
@@OnlySamCan That is true, however the problem lies with all of the nodes being instanced and you will start to see frame drops whenever a chunk is generated.
can i implement the animal scripts from your main game into my game? i managed to spawn in moving animals for my game with your code, just asking for permission to keep the feature.
Sure, the stuff on git hub is a very old version of the project and most of the stuff there was learnt from the heart beast action rpg series.
could you translate this to a 3d space?
Yes, just use the altitude noise to offset a mesh by that amount, rather than using a tilemap
why not subtitles? :'v i can't watch the subtitles
I’m about to add them I just need to update the script
@@slothinahat It's ok, nothing happens :3, it's better that way I make an effort to understand English, I love it uwu
I just added them though they will take some time to process.
Why don't you say p-ah-s for pos instead of pose? The pos variable is short for position so calling it pose sounds weird like you don't know what it stands for
an error occurred :, v, I'm at the end of the tutorial 4:45, and this error appears:
Invalid get index of type "String" (on base: "Dictionary").
and send me here:
var instance = objetos_de_bioma[str(random_object)].instance()
It may be because the biome or object name you provided was spelled differently in the tiles/object tiles dictionary. Try to check that all of the spellings for the names match
@@slothinahat hmm oka
@@slothinahat I've already fixed it!, I hadn't put the other biomes, that is, their random objects were empty xD, thank you very much for teaching us
Yeah as long as it is in a string you can put whatever you want
hii, you have discord?