The source code and project files are now available on GitHub: github.com/Thoughtquake/dungeon-of-recycling Note: Some bugs were found after the video that have not been fixed (yet.)
I'd be super interested in a video about refactoring this code for a newer godot release. I've really enjoyed this tutorial, I'm following along right now and after it's finished I want to take a step back and see how I could update it based on what I've learned :D
@@teejay9189 I'm waiting until I finish my current project to switch to 4.0, so I haven't researched the differences yet. I'll probably make an updated tutorial when I do, but that won't be for at least a few months.
Timeline: 1:00 - Part 1: Initial Setup 5:11 - Part 2: Level Generation 16:34 - Part 3: Movement 19:12 - Part 4: Level Progession 21:13 - Part 5: Vision Limiting 24:21 - Part 6: Enemies 34:17 - Part 7: Items
As a programmer used to unity, this 40 minute tutorial has told me more about how godot works and how to actually use the language than i could possible get from 100 "normal" tutorials. Thank you SO MUCH for this awesome quickstart, making an interesting product too!
Update for Godot 4.0 - Because the tileset is a bunch of loose images, , Godot 4 considers them to each be an AtlasMap, each with one coordinate.. Hence, set_cell(x, y, Tile.Door) becomes set_cell(0, Vector2(x, y), Tile.Door, Vector2(0,0)).
to be honest, Godot is pretty self-documenting. I found out how to do a lot of things just by searching nodes. Documentation is also quite good. JUST DO IT!
The Godot documentation is very well explained, for some reason people like to say that Godot do not have good documentation, for sure they never looked at the godot docs. But the true part is that we have a lack of good godot tutorials (this is changing quickly) , in the other side Unity have a lot of good video tutorials.
@@heavy5756 When people say "Godot doesn't have good documentation" what they actually mean is "There aren't enough handholding UA-cam tutorials that tell me how to remake fortnite"
For everyone in godot 3.2 the segment about the visual doesn't seem to work properly in this version. So I've found a way to make it work. First off the update_visuals can't be called when a room is just barely finished. So what I did to fix this was create a timer right before I updated the visuals when the room is first created AND when you move to a new floor. EXAMPLE 1. var startRoom = rooms.front() var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2) var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2) player_tile = Vector2(playerX, playerY) yield(get_tree().create_timer(.2), "timeout") call_deferred("update_sight") EXAMPLE 2. func try_move(dx, dy): var x = player_tile.x + dx var y = player_tile.y + dy
var tileType = Tile.Stone if x >= 0 && x < levelSize.x && y >= 0 && y < levelSize.y: tileType = map[x][y]
match tileType: Tile.Floor: player_tile = Vector2(x, y)
call_deferred("update_sight") This is how I was able to fix the bug where the visual doesn't completely work. You can mess with the timer and how much it waits, I just tested it with .2 and it made it work. I hope this helps anyone using godot 3.2. Love yourself P.S. I've personally set my timer to 0.01 and that seemed to work just fine. Make's for a quick reload speed
YOU ARE THE BOSS, THIS WORKED PS: this problem was also happening with the Tile.Door part, so I added yield(get_tree().create_timer(.1), "timeout") there too the delay between opening the door and seeing what's inside actually gives it suspense :D
This fix works better when I instead put the yield() call inside of update_visuals(), after the line that updates the player's position. Otherwise, the player sprite would noticeably flicker as I moved. Also, disabling VSync causes it not to work.
@@cadex80 I didn't even think of putting the yield into update_visuals()! That would work better since you wouldn't have to put it in front of every call for update_visuals(). Also I never disabled VSync, but I'll take your word for it
Thanks, I was wondering what I was doing incorrectly. If I may suggest a somewhat cleaner solution, I would use _yield(get_tree(), "idle_frame")_ in update visuals instead. This works perfectly fine for me, although it is very weird, since this is what call_deferred should achieve anyway, as far as I understand it. func update_visuals(): player.position = player_tile * TILE_SIZE *yield(get_tree(), "idle_frame")* var player_center = tile_to_pixel_center(player_tile.x, player_tile.y) var space_state = get_world_2d().direct_space_state for x in range(level_size.x): for y in range(level_size.y): if visibility_map.get_cell(x,y) == 0: var x_dir = 1 if x < player_tile.x else -1 var y_dir = 1 if y < player_tile.y else -1 var test_point = tile_to_pixel_center(x,y) + Vector2(x_dir, y_dir) * TILE_SIZE/2 var occlusion = space_state.intersect_ray(player_center, test_point) if !occlusion or (occlusion.position - test_point).length() < 1: visibility_map.set_cell(x,y,-1)
ur little diagrams on the side that explain the code points are extremely helpful, and is whats missing from all the other tutorials out there. thank you for the amazing tutorial!
So after more than an hour of debugging I found that, when you import tiles to the tile map, they are assigned a number. The Tile enum needs to have the tile names listed in the order that they are listed in the scene. You can find that by selecting the TileMap in the scene, then clicking Tilemap in the inspector. A drop down will appear with the top node being "TileSet". Select that and you'll be able to see which number each tile is assigned to.
Thanks, I knew it was something like this, but there was a lot of GODOT things that aren't really explained here. I understand the programming. Now to figure out how to reassign the numbers.
@@luke_rs , going back and deleting the TileMap and then creating the tiles in the order Thoughtquake did solved it for me. It was an interesting problem and some good learning for me. Have fun! I know that I am!
Ty, I think I understand better now. In 3.2 is a little different, you now have to select the tile (after selecting the tileset in the tilemap node), then press the yellow 'i' below new Atlas to see the number and the name, you have to deselect and select again if the tiles are different. No idea how to reassing those tho, besides deleting the tilemap or creating a new tile
I appreciate the console being open at the bottom. I'm trying to get started with Godot, and that makes picking up the specific actions I'm watching, clearer. Thanks for that!
It would've taken me a month to create a procedurally generated level code. I'm checking out godot and these are the types of tuts I enjoy watching and seem the most helpful.
Thanks for another great tutorial! Don't worry about doing less of them. Focus on your cool game idea and make more great Godot content! Loved the theme of this roguelike, too. Hilarious idea with the recycling can and bags of garbage.
great tutorial. i had a bit of trouble in the level generation part, but it worked great as a debugging training. And as you stated in your vid, it is a good case for unit testing.
Brilliant tutorial I've been looking for, I do believe rogue likes are great for learning programming seeing as it teaches you so much and you could do anything with them. Good tutorial 👍👍
Found a bug in my code: When I reset impairment_turns, poison_turns, and healing_turns for restarting the game, I didn't hide the corresponding labels or light. Oops!
Found another one: It's possible for rooms to spawn wall to wall to each other, with a door that leads nowhere :D I added a two tile margin to each room to fix this issue.
Hey Guys. I have a problem with the Level Generation part. When i try to run it, i recieve an error: "Assertion failed". Has anyone an idea how i could fix this?
Great video. Until now, I've used Java to create a roguelike from scratch, but I might just try Godot because I'm still very new to coding, and I think I can learn a lot with an Engine like this one.
I don't think that making everything in one script file was good for the tutorial. Even though the game is simplistic, it's still a lot of code that could've been neatly arranged in different files, that's the whole idea behind Godot's node hierarchy. Not speaking to the quality of the code itself, organizing it better would've made it easier to understand how all the methods interact with each other. Otherwise, a great tutorial.
That's fair. It would be a better example of how to do things for a real game if I used multiple scripts. I just spent so long on this as-is, at some point I had to call it good enough and stop trying to make it better.
Nah. His one-script-has-all format was an innovation to tutorials. And you failed to see it. You can do organization by yourself. Evangelizing a way of doing things doesn't always necessarily fit a type of work such as this - a tutorial about making a kind of game - that was the goal. He hit it perfectly.
@@noiJadisCailleach As someone who as seen many many tutorials which say, "I'm doing this the quick way, but don't do this when you code it for real!", but never tell you what was wrong with the way they did things, or how to "code it for real", I'm going to have to heartily disagree. Learning something the right way the first time is better than learning something the wrong way, have no idea what you learned wrong, and then take years to correct and unlearn.
Get a recomendation on why to chose Godot from YT, be convinced, decide to make a rogue clone to get confortable whit the engine, suscribe to the channel and browse around, find a tutorial on how to build a Roguelike in godot. MFW YT knows what im about to do better than myself. Great content man, I will totaly see the series on your game in the background while i make my Rogue clone :)
Amazing tutorial, thanks! One problem I have is that, for some reason, the game seems to run a bit slower on each consecutive level, even with at the same room sizes. I have a feeling it has to do with the visibility / occlusion, but I can't figure it out. Anyone else run into this?
There is an easier solution to rendering the enemies invisible: Just add a Node2D to the Scene Tree, make sure it is positioned above the VisibilityMap. Call it "Enemies". Instead of adding the enemies as children of the Game Node, add them to the Enemies Node: _game.get_node("Enemies").add_child(sprite_node)_ Since the doors are locked before the player opens them, there will be no path to the player. Therefore, the enemies will do nothing anyways, until the player discovers them. That's already it, no raycasting required ^^
@Thoughtquake. Thanks to your tutorial, I was finally able to finish and publish a game. If you have a moment to check it out on Game of the Month, I'd be grateful. gotm.io/alerion-games/procgen Thanks for your great tutorial and help! p.s. if you could do a video on how to break this apart in multiple nodes and scripts that would be nice. Additionally more tutorials from you would be sweet!
Absolutely wonderful tutorial. I love the fast past content rich style. So much in one video. Don't listen to the nay-sayers about too fast or one script being a problem. This is great. It has great building blocks to learn and if they can't split this code into multiple scripts to fit their game they aren't ready for a tutorial of this level. I know it is a ton of work but looking forward to another amazing tutorial.
This is really great but hard to keep up with. This material seems aimed at intermediate level but presented like we're racing to get done. Still excellent and of course I can slow it down etc.
Thanks! I have a bad habit of moving too fast because I dislike long-winded tutorials full of long pauses and such, but I'll try to work on the balance a bit more for the next one.
Also, around 3 min in, you fixed the player cam by turning down the drag margins, you can effectively do the same by ticking the drag margin check boxes off.
The visibility tileset uses only a single tile whereas autotile is intended to mash together different tiles automatically so I don't see the relevancy
It was a lot of fun! Now I'm re-doing the tutorial with a focus on what I need my game to be. I'm focusing on teaching radiation safety. Therefore, there is a Personal Protective Equipment (PPE) Level N (Nothing), MnG (Mask and Gloves), D (normal uniform with mask and gloves), C (PAPR and Tyvek), B (SCBA with Tyvek), and A (SCBA with Tyvek, total space suit). I also have to put in the inverse square law and shielding for the walls. My enemies are stationary isotopes that don't move, but they do give out a dose rate that falls off by the square of the distance. This core program is a good one to adapt to my needs IMO. I just have to be smarter and know who I can ask for help. Thanks!
Not sure if anyone will see this as this video is pretty old at this point but im having troubles with the generation of the levels. The code runs fine with no errors but the tiles wont show up so its just my character in the middle and the UI at the top but no tiles, any ideas?
This video keeps all of his promises. Would look again! You just got a lot of shit done in this one. Even thought I would liked if you took time to split it up into a proper project structure. And I think that some links in the description that covers "level generation" (Books or Tutorials) would make this more complete.
Hi Friend, amazing tutorial and i'm not even done... I used a sprite and scene sheet, how do I create the enum part in the script since I only have 1 image for the whole game and I've been selecting each sprite or tile I need from that sheet. I see you enum different variables with the same name of the png images, does this matter? thenks a lot!!
The enum is just a way to put labels on the tile indexes so things are easy to read. It doesn't matter if the tiles come in one image or many; just need the enum names to be in order by tile index, or manually set the value for each.
EXAMPLE var startRoom = rooms.front() var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2) var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2) player_tile = Vector2(playerX, playerY) yield(get_tree().create_timer(.2), "timeout") call_deferred("update_sight") Create a timer before you update the visuals. It doesn't work whenever the room is done building itself rightaway. Check out my comment on this video to see my full explanation
Currently tutorial project downloads are a perk for Patreon supporters, but since I'm not doing tutorials regularly anymore I might remove that tier and open them to the public in the future. I'm not sure yet.
I love the tutorial! Thanks! However, I was an OK coder back in the 1980s, and taking a 35 year vacation from coding hasn't helped me. For some reason even though my art is 1 kb, the files are showing up like they are huge when I put the grid on them. This corresponds to time stamp 2:25 in your tutorial. Any advice on getting this art to fit? My png files are tiny but apparently not tiny enough.
I restarted from the beginning (I was only just over 2 minutes into your presentation, no biggie) and went through the process again. Now the icons work! And, I got to do the process again and re-enforced what I learned. Win-win! Yeah, I'm effectively treating Thoughtquake like a rubber duck here. :( Please forgive an old veteran who wants to code again. I miss the old machine language coding, even though it took us weeks to anything at all.
Apparently 15 pixels by whatever isn't large enough, but it's close. I'm learning! And, I've done the first 3 minutes so many times I no longer have to look at the video anymore for that section! Successful learning through repeated failure!
15 pixels by whatever was way too small. 45 pixels by whatever was too big but close. It looks like 30 pixels by whatever works pretty well at least for square objects.
Up to 4:18. Effectively I'm 10% done! Yeah! But I had to slow down the video to 25% speed and now you sound like someone who is very, very, very drunk yet still coding amazingly well. Sort of like learning from Tony Stark I guess.
Very good tutorial, works with minor graphics bug for me until items (or late AI, didn’t check game for a while) in which I get a “the identifier “items” isn’t declared in the current scope.” For ‘for item in items’ and with the small changes I made, and no serious Godot knowledge I was sure to run into something eventually. I also got a prior debug with AStar which may also have made it unplayable. Definitely the most functional thing I’ve made on godot despite that.
I think I’ve seen another comment with graphics issues, but in my issue, bricks appear black, which doesn’t mesh well with the black background, stone is the background color (grey then black) ladders are my equivalent of paper.png, enemies, doors and the player look fine. I’ll post a solution if I find one.
Thanks for your very good tutorial! Subscribed. But at 14:36, we use target_point as a parameter. I don't know if I missed out on something or it is different now in Godot 3.2, but where exactly is target_point defined? Cause it gives me as an error "error (145,1): unexpected token: Identifier:func_get_nearest_unconnected_point" right under the editor, and the debugger also gives me "Parser Error: Unexpected token: Identifier:func_get_nearest unconnected_point". I searched through the video, but I did not find where "target_point" was defined. When I try to run the code, it doesn't work. Worked fine before, generating the rooms only.
Would this method work on a 3D Rogue-like game? Say I had premade 3d models and rooms and items and what not, would I back able to make them load in randomly puzzled together?
Can you PLEASE give the code on github. im getting an err even though i did everything you did.(At least that's what I think) for region in free_regions: if region.intersects(region_to_remove): removal_queue.append(region) it says: Invalid type in function 'intersects' in base Rect2. cannot convert argument 1 from Array to Rect2. please help
Anyone getting a error on the "add_room"(free_regions) line? It's in the Func build_level(): lines. I have it written the same way. Even looked on his github at the code. It's all the same. Getting a (unused argument) error.
Great tutorial, but I'm stuck on the visibility map. space_state.intersect_ray(player_center, test_point) ALWAYS returns an empty dictionary, so on the first run of update_visuals it always EVERY tile in visibility map to -1. I've checked my tilemap and the wall, stone and door tiles have collision shapes, which I verified with visible collision shapes in the debug menu. I tried adding occlusion shapes, but it made no difference. I've read the documentation of the Physics2DDirectSpaceState, I've tried passing a collision_layer value into intersect_ray, but nothing works. Any ideas on how to troubleshoot further? It seems that intersect_ray either doesn't get the correct input somehow, OR somehow MY instance of it works differently, so returns different output for the same input.
EXAMPLE var startRoom = rooms.front() var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2) var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2) player_tile = Vector2(playerX, playerY) yield(get_tree().create_timer(.2), "timeout") call_deferred("update_sight") Create a timer before you update the visuals. It doesn't work whenever the room is done building itself rightaway. Check out my comment on this video to see my full explanation
for me this worked the best: func update_visuals(): player.position = player_tile * TILE_SIZE yield(get_tree().create_timer(0.000001), "timeout") #and the rest of the function is the same as in tutorial
I'm getting weird bugs where I don't actually spawn inside a room, and I cant move, hopefully I can figure it out but the more I go along more the errors I find, 19:11
OKAY I FINALLY FIXED THE CODE ALL ROOMS CONNECT AND MY PLAYER MOVES PERFECT, really ember to take breaks when having errors to easily find the solutions. my problem was that I had a lot of my x and y mixed up
random thing here - it's cool to see another person using Sublime text. have you also checked out Liclipse? And have you tried MS Visual Studio Code? I've been using Code for a while now on C++, Python, Lua, and even an industrial robot arm action-script (using python syntax highlighting which works alright).
@@jplay9710 This is debated a lot; you're right that it's named after the French play and that's how I've been pronouncing it, but the creator of the Godot engine pronounced it differently (rhyming with robot) in a GDC talk. To be honest I'm sticking with the French pronunciation just because otherwise I expect a lot more people would try to correct me the other way.
if you want to do pixel art; paint(dot)net is pretty good, it's tiny, fast and free. for non pixel art stuff I use Krita. have a look at mortmort on youtube, he makes pixel art tutorials and tip videos.
Personally I would always make my own art when following tutorials like this. Makes it much more fun and feels more like "your own creation". For this you really just need to open up paint or gimp and fire up a couple of 32x32 tiles, takes 5 minutes and you can always come back later and make them prettier.
Hey there, Thoughtquake. I've been watching your tutorial and following carefully, but I can't seem to figure out why the 'for i in range(num_rooms)' thing does not work for me. It says that 'for' is the unexpected token for some reason? I have tried removing it (obviously didn't work lol) and rewriting that part and some parts behind it completely, but that did not work either. Do you know the solution? The exact thing that it says for me is 'error(58,1) Unexpected token: for:' Thanks in advance.
@@Thoughtquake I figured it out. Turns out I didn't even write an entire line of code! Thanks for the tutorial man, I have a ton of game ideas and thanks to your tutorial I can make it come true.
If you want to make a roguelike like a Mario maker, there is a game called `` Nanaka Mysterious Labyrinth Record '' take-hisa.com/nanaka/ もしもローグライクをマリオメーカーのように作りたいなら「ナナカ 不思議の迷宮録」というゲームがあります take-hisa.com/nanaka/
Would have been nice but for two things. You go way too fast, and I have to pause and rewind way too much. Second, you should have supplied the art you made so we could follow along.
It just seemed the easiest way to get it done quickly, and I didn't think about changing it until I was half-way through recording. Starting over would have taken a lot of time and I didn't think it would bother anyone as-is.
I hope you know comments like yours can really ruin someone's day. If it weren't for the larger number of people being positive and encouraging, I'd have given up on UA-cam completely by now. But that's what you want, isn't it?
I didn’t meant to hurt you. I am really sorry about that and I want to apologize. I really thought you did intentionally wrote the long code just for fun. I hope you don’t feel bad anymore. I will delete original comment if you want.
@@빵빵빵-m1o Maybe I misread your intent when you said it was "painful to watch". I get a lot of hateful comments and assumed you were just another person trying to insult my intelligence and discourage me from making videos.
I got 5 mins in, and realized you didn't provide the art, not much of a tutorial if you can't follow along. Plus you go at light speed. This one's a dud
The source code and project files are now available on GitHub: github.com/Thoughtquake/dungeon-of-recycling
Note: Some bugs were found after the video that have not been fixed (yet.)
wow the video is 1 Year old, guess i came at the perfect time ! thank you !
I'd be super interested in a video about refactoring this code for a newer godot release. I've really enjoyed this tutorial, I'm following along right now and after it's finished I want to take a step back and see how I could update it based on what I've learned :D
what's the difference in coding this in 4.0?
@@teejay9189 I'm waiting until I finish my current project to switch to 4.0, so I haven't researched the differences yet. I'll probably make an updated tutorial when I do, but that won't be for at least a few months.
@@Thoughtquake Well, pop_back() seems to be removed and I can't see any way to reference it on a packed int array, so there's that
Timeline:
1:00 - Part 1: Initial Setup
5:11 - Part 2: Level Generation
16:34 - Part 3: Movement
19:12 - Part 4: Level Progession
21:13 - Part 5: Vision Limiting
24:21 - Part 6: Enemies
34:17 - Part 7: Items
Спасибо тебе человек, который меня не поймёт!
As a programmer used to unity, this 40 minute tutorial has told me more about how godot works and how to actually use the language than i could possible get from 100 "normal" tutorials. Thank you SO MUCH for this awesome quickstart, making an interesting product too!
Update for Godot 4.0 -
Because the tileset is a bunch of loose images, , Godot 4 considers them to each be an AtlasMap, each with one coordinate.. Hence, set_cell(x, y, Tile.Door) becomes set_cell(0, Vector2(x, y), Tile.Door, Vector2(0,0)).
The only reason why I don't switch from unity to godot is because unity has more tutorials. So thanks for changing that :D
to be honest, Godot is pretty self-documenting. I found out how to do a lot of things just by searching nodes. Documentation is also quite good. JUST DO IT!
The Godot documentation is very well explained, for some reason people like to say that Godot do not have good documentation, for sure they never looked at the godot docs. But the true part is that we have a lack of good godot tutorials (this is changing quickly) , in the other side Unity have a lot of good video tutorials.
and the best part is unity tutorials are fairly easy to convert to Godot once you get into it
I agree 100% dropping godot like a toilet seat...not enough support!
@@heavy5756
When people say "Godot doesn't have good documentation" what they actually mean is "There aren't enough handholding UA-cam tutorials that tell me how to remake fortnite"
00:00 Intro / What's inside this tutorial
00:59 Initial Setup
05:10 Level Generation
16:33 Movement
21:13 Vision Limiting
24:21 Enemies
34:16 Items
For everyone in godot 3.2 the segment about the visual doesn't seem to work properly in this version. So I've found a way to make it work. First off the update_visuals can't be called when a room is just barely finished. So what I did to fix this was create a timer right before I updated the visuals when the room is first created AND when you move to a new floor.
EXAMPLE 1.
var startRoom = rooms.front()
var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2)
var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2)
player_tile = Vector2(playerX, playerY)
yield(get_tree().create_timer(.2), "timeout")
call_deferred("update_sight")
EXAMPLE 2.
func try_move(dx, dy):
var x = player_tile.x + dx
var y = player_tile.y + dy
var tileType = Tile.Stone
if x >= 0 && x < levelSize.x && y >= 0 && y < levelSize.y:
tileType = map[x][y]
match tileType:
Tile.Floor:
player_tile = Vector2(x, y)
Tile.Door:
set_tile(x, y, Tile.Floor)
Tile.Stairs:
levelNum += 1
if levelNum < LEVEL_SIZES.size():
build_level()
yield(get_tree().create_timer(.2), "timeout")
call_deferred("update_sight")
else:
print("win")
call_deferred("update_sight")
This is how I was able to fix the bug where the visual doesn't completely work. You can mess with the timer and how much it waits, I just tested it with .2 and it made it work. I hope this helps anyone using godot 3.2. Love yourself
P.S. I've personally set my timer to 0.01 and that seemed to work just fine. Make's for a quick reload speed
YOU ARE THE BOSS, THIS WORKED
PS: this problem was also happening with the Tile.Door part, so I added
yield(get_tree().create_timer(.1), "timeout")
there too
the delay between opening the door and seeing what's inside actually gives it suspense :D
@@PinguinoSod I did the same thing and i would agree! I'm glad I could help!
This fix works better when I instead put the yield() call inside of update_visuals(), after the line that updates the player's position. Otherwise, the player sprite would noticeably flicker as I moved.
Also, disabling VSync causes it not to work.
@@cadex80 I didn't even think of putting the yield into update_visuals()! That would work better since you wouldn't have to put it in front of every call for update_visuals(). Also I never disabled VSync, but I'll take your word for it
Thanks, I was wondering what I was doing incorrectly. If I may suggest a somewhat cleaner solution, I would use
_yield(get_tree(), "idle_frame")_
in update visuals instead. This works perfectly fine for me, although it is very weird, since this is what call_deferred should achieve anyway, as far as I understand it.
func update_visuals():
player.position = player_tile * TILE_SIZE
*yield(get_tree(), "idle_frame")*
var player_center = tile_to_pixel_center(player_tile.x, player_tile.y)
var space_state = get_world_2d().direct_space_state
for x in range(level_size.x):
for y in range(level_size.y):
if visibility_map.get_cell(x,y) == 0:
var x_dir = 1 if x < player_tile.x else -1
var y_dir = 1 if y < player_tile.y else -1
var test_point = tile_to_pixel_center(x,y) + Vector2(x_dir, y_dir) * TILE_SIZE/2
var occlusion = space_state.intersect_ray(player_center, test_point)
if !occlusion or (occlusion.position - test_point).length() < 1:
visibility_map.set_cell(x,y,-1)
ur little diagrams on the side that explain the code points are extremely helpful, and is whats missing from all the other tutorials out there. thank you for the amazing tutorial!
So after more than an hour of debugging I found that, when you import tiles to the tile map, they are assigned a number. The Tile enum needs to have the tile names listed in the order that they are listed in the scene. You can find that by selecting the TileMap in the scene, then clicking Tilemap in the inspector. A drop down will appear with the top node being "TileSet". Select that and you'll be able to see which number each tile is assigned to.
You save me some time thanks
Thanks, I knew it was something like this, but there was a lot of GODOT things that aren't really explained here. I understand the programming. Now to figure out how to reassign the numbers.
@@luke_rs , going back and deleting the TileMap and then creating the tiles in the order Thoughtquake did solved it for me. It was an interesting problem and some good learning for me. Have fun! I know that I am!
Ty, I think I understand better now. In 3.2 is a little different, you now have to select the tile (after selecting the tileset in the tilemap node), then press the yellow 'i' below new Atlas to see the number and the name, you have to deselect and select again if the tiles are different. No idea how to reassing those tho, besides deleting the tilemap or creating a new tile
I appreciate the console being open at the bottom. I'm trying to get started with Godot, and that makes picking up the specific actions I'm watching, clearer. Thanks for that!
Godot now has a dedicated Astar2D class in latest 3.2 beta
Amazing tutorial! The best 1.5 hours I've spent on UA-cam (I watched it twice). Thank you very much.
I was honestly looking for a tutorial like the since the last week. Thank you! I hope that your own game rocks the show!
It would've taken me a month to create a procedurally generated level code.
I'm checking out godot and these are the types of tuts I enjoy watching and seem the most helpful.
Oh wow! I've always wanted to learn how to make a rogue like and now with godot! I'll definitely give this a try soon, thank you so much!
Thanks for another great tutorial! Don't worry about doing less of them. Focus on your cool game idea and make more great Godot content!
Loved the theme of this roguelike, too. Hilarious idea with the recycling can and bags of garbage.
great tutorial. i had a bit of trouble in the level generation part, but it worked great as a debugging training. And as you stated in your vid, it is a good case for unit testing.
Thank you for the tutorial! Thank your for explaining each step as you went through it
i wish i can support your endeavor. your tutorials is just the pace i really needed.
Brilliant tutorial I've been looking for, I do believe rogue likes are great for learning programming seeing as it teaches you so much and you could do anything with them. Good tutorial 👍👍
Thanks, man! This tutirial is realy cool.
Fantastic tutorial. Thanks!
Found a bug in my code: When I reset impairment_turns, poison_turns, and healing_turns for restarting the game, I didn't hide the corresponding labels or light. Oops!
That part can be figured by us ourself. Thanks for pointing that out
it happens.
Found another one: It's possible for rooms to spawn wall to wall to each other, with a door that leads nowhere :D
I added a two tile margin to each room to fix this issue.
If anyone else experiences weird flickering tiles, I turned off VSync and the flickering was gone! Great tutorial!
Man I am so happy you made this! I love Godot!
After watching this tutorial, I decided to work with godot : )
Wow, very impressive. Thanks.
Hey Guys.
I have a problem with the Level Generation part.
When i try to run it, i recieve an error: "Assertion failed".
Has anyone an idea how i could fix this?
Having some issues with godot4 and the vision. The raycasting will incorrectly tag tiles far beyond other cells as no occlusion.
Great video. Until now, I've used Java to create a roguelike from scratch, but I might just try Godot because I'm still very new to coding, and I think I can learn a lot with an Engine like this one.
I don't think that making everything in one script file was good for the tutorial. Even though the game is simplistic, it's still a lot of code that could've been neatly arranged in different files, that's the whole idea behind Godot's node hierarchy. Not speaking to the quality of the code itself, organizing it better would've made it easier to understand how all the methods interact with each other. Otherwise, a great tutorial.
That's fair. It would be a better example of how to do things for a real game if I used multiple scripts. I just spent so long on this as-is, at some point I had to call it good enough and stop trying to make it better.
Nah. His one-script-has-all format was an innovation to tutorials. And you failed to see it.
You can do organization by yourself.
Evangelizing a way of doing things doesn't always necessarily fit a type of work such as this - a tutorial about making a kind of game - that was the goal. He hit it perfectly.
@@noiJadisCailleach bruh.
@@noiJadisCailleach Are you on drugs?
@@noiJadisCailleach As someone who as seen many many tutorials which say, "I'm doing this the quick way, but don't do this when you code it for real!", but never tell you what was wrong with the way they did things, or how to "code it for real", I'm going to have to heartily disagree. Learning something the right way the first time is better than learning something the wrong way, have no idea what you learned wrong, and then take years to correct and unlearn.
Get a recomendation on why to chose Godot from YT, be convinced, decide to make a rogue clone to get confortable whit the engine, suscribe to the channel and browse around, find a tutorial on how to build a Roguelike in godot. MFW YT knows what im about to do better than myself. Great content man, I will totaly see the series on your game in the background while i make my Rogue clone :)
Amazing tutorial, thanks! One problem I have is that, for some reason, the game seems to run a bit slower on each consecutive level, even with at the same room sizes. I have a feeling it has to do with the visibility / occlusion, but I can't figure it out. Anyone else run into this?
quite late, but yes, and the problem seems to be the enemies, they're probably stacking up data each level, which could be problematic
So
When I write all the code lines until the level generation finishes, all is okay, but my level do not generates anything
Anyone know why?
it's something with the room.clear map.clear and tile_map.clear
Very dirty code, but very inspirational tutorial. Also very compact in a good way. Kudos.
Does anyone else find that the value returned by *start_room_id* is an integer value inconsistent with the index value required for rooms?
There is an easier solution to rendering the enemies invisible:
Just add a Node2D to the Scene Tree, make sure it is positioned above the VisibilityMap.
Call it "Enemies".
Instead of adding the enemies as children of the Game Node, add them to the Enemies Node:
_game.get_node("Enemies").add_child(sprite_node)_
Since the doors are locked before the player opens them, there will be no path to the player. Therefore, the enemies will do nothing anyways, until the player discovers them.
That's already it, no raycasting required ^^
I tried until part 5, but the visibility doesn't work for me... Any idea?
is the code to this posted on github anywhere? can we download it?
I know this is very late, but it's on GitHub now: github.com/Thoughtquake/dungeon-of-recycling
@Thoughtquake. Thanks to your tutorial, I was finally able to finish and publish a game. If you have a moment to check it out on Game of the Month, I'd be grateful. gotm.io/alerion-games/procgen
Thanks for your great tutorial and help!
p.s. if you could do a video on how to break this apart in multiple nodes and scripts that would be nice. Additionally more tutorials from you would be sweet!
Absolutely wonderful tutorial. I love the fast past content rich style. So much in one video. Don't listen to the nay-sayers about too fast or one script being a problem. This is great. It has great building blocks to learn and if they can't split this code into multiple scripts to fit their game they aren't ready for a tutorial of this level.
I know it is a ton of work but looking forward to another amazing tutorial.
everything is great except my starting room never has a door
"Dungeon of Recycling -- No Exit Edition". Put it up somewhere and call it a metaphor for life ;)
This is really great but hard to keep up with. This material seems aimed at intermediate level but presented like we're racing to get done. Still excellent and of course I can slow it down etc.
Thanks! I have a bad habit of moving too fast because I dislike long-winded tutorials full of long pauses and such, but I'll try to work on the balance a bit more for the next one.
Also, around 3 min in, you fixed the player cam by turning down the drag margins, you can effectively do the same by ticking the drag margin check boxes off.
The visibility tileset is a great idea. Consider making it an autotile to make it more detailed 👀
The visibility tileset uses only a single tile whereas autotile is intended to mash together different tiles automatically so I don't see the relevancy
Thank you very much. God bless
It was a lot of fun! Now I'm re-doing the tutorial with a focus on what I need my game to be. I'm focusing on teaching radiation safety. Therefore, there is a Personal Protective Equipment (PPE) Level N (Nothing), MnG (Mask and Gloves), D (normal uniform with mask and gloves), C (PAPR and Tyvek), B (SCBA with Tyvek), and A (SCBA with Tyvek, total space suit). I also have to put in the inverse square law and shielding for the walls. My enemies are stationary isotopes that don't move, but they do give out a dose rate that falls off by the square of the distance. This core program is a good one to adapt to my needs IMO. I just have to be smarter and know who I can ask for help. Thanks!
Not sure if anyone will see this as this video is pretty old at this point but im having troubles with the generation of the levels. The code runs fine with no errors but the tiles wont show up so its just my character in the middle and the UI at the top but no tiles, any ideas?
This video keeps all of his promises. Would look again!
You just got a lot of shit done in this one. Even thought I would liked if you took time to split it up into a proper project structure. And I think that some links in the description that covers "level generation" (Books or Tutorials) would make this more complete.
kinda got stuck at 7:00 because I get an empty scene with no tiles. edit: turns out the first tile of tile_map is index 1, not index 0
Hi Friend, amazing tutorial and i'm not even done... I used a sprite and scene sheet, how do I create the enum part in the script since I only have 1 image for the whole game and I've been selecting each sprite or tile I need from that sheet. I see you enum different variables with the same name of the png images, does this matter? thenks a lot!!
The enum is just a way to put labels on the tile indexes so things are easy to read. It doesn't matter if the tiles come in one image or many; just need the enum names to be in order by tile index, or manually set the value for each.
I'm Having trouble with the set tile argument. Theres too many arguments and I don't know how to fix it. plz help.
i am having the same issue
First time gonna to make my procedural tiled map generation. Thanks for your video. Can you give result build to try to play?
anyone here has problem with the occlusion and limited vision?
EXAMPLE
var startRoom = rooms.front()
var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2)
var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2)
player_tile = Vector2(playerX, playerY)
yield(get_tree().create_timer(.2), "timeout")
call_deferred("update_sight")
Create a timer before you update the visuals. It doesn't work whenever the room is done building itself rightaway. Check out my comment on this video to see my full explanation
I do
Half of the map is already displayed at the beginning, and a lot of tiles that should not be revealed, are revealed when a door is opened.
@Thoughtquake : Thanks for this tutorial. Any chance you could share the code on GitHub or somewhere?
Currently tutorial project downloads are a perk for Patreon supporters, but since I'm not doing tutorials regularly anymore I might remove that tier and open them to the public in the future. I'm not sure yet.
Dude your amazing!
you're
@@arturkarlov3000 Dude is this the best you can do with your time?
@@c0d3d85 it really didn't take much of it.
@@arturkarlov3000 lol
I love the tutorial! Thanks! However, I was an OK coder back in the 1980s, and taking a 35 year vacation from coding hasn't helped me. For some reason even though my art is 1 kb, the files are showing up like they are huge when I put the grid on them. This corresponds to time stamp 2:25 in your tutorial. Any advice on getting this art to fit? My png files are tiny but apparently not tiny enough.
I restarted from the beginning (I was only just over 2 minutes into your presentation, no biggie) and went through the process again. Now the icons work! And, I got to do the process again and re-enforced what I learned. Win-win! Yeah, I'm effectively treating Thoughtquake like a rubber duck here. :( Please forgive an old veteran who wants to code again. I miss the old machine language coding, even though it took us weeks to anything at all.
Drat! My art is still too big. Back to the drawing board!
Apparently 15 pixels by whatever isn't large enough, but it's close. I'm learning! And, I've done the first 3 minutes so many times I no longer have to look at the video anymore for that section! Successful learning through repeated failure!
15 pixels by whatever was way too small. 45 pixels by whatever was too big but close. It looks like 30 pixels by whatever works pretty well at least for square objects.
Up to 4:18. Effectively I'm 10% done! Yeah! But I had to slow down the video to 25% speed and now you sound like someone who is very, very, very drunk yet still coding amazingly well. Sort of like learning from Tony Stark I guess.
What addons are you using with sublime to work with gdscript
Very good tutorial, works with minor graphics bug for me until items (or late AI, didn’t check game for a while) in which I get a “the identifier “items” isn’t declared in the current scope.” For ‘for item in items’ and with the small changes I made, and no serious Godot knowledge I was sure to run into something eventually. I also got a prior debug with AStar which may also have made it unplayable. Definitely the most functional thing I’ve made on godot despite that.
Update, figured out the error with items. (Missed a Variable statement)
Update, a spelling error caused the AI bug.
I can also see the enemies in the dark which is a bug, but my graphics as a whole are bugged so I couldn’t care at the moment.
I think I’ve seen another comment with graphics issues, but in my issue, bricks appear black, which doesn’t mesh well with the black background, stone is the background color (grey then black) ladders are my equivalent of paper.png, enemies, doors and the player look fine. I’ll post a solution if I find one.
I also think visibility is bugged in general, it would explain the enemy png visibility and I can’t know for sure until graphics are fixed
Thanks for your very good tutorial!
Subscribed.
But at 14:36, we use target_point as a parameter. I don't know if I missed out on something or it is different now in Godot 3.2, but where exactly is target_point defined?
Cause it gives me as an error "error (145,1): unexpected token: Identifier:func_get_nearest_unconnected_point" right under the editor, and the debugger also gives me "Parser Error: Unexpected token: Identifier:func_get_nearest unconnected_point".
I searched through the video, but I did not find where "target_point" was defined.
When I try to run the code, it doesn't work.
Worked fine before, generating the rooms only.
Thank you.
When i do the Tile.Wall and Tile.Stone. stone is nothing and wall is my stone sprite, how do i fix this?
Would this method work on a 3D Rogue-like game?
Say I had premade 3d models and rooms and items and what not, would I back able to make them load in randomly puzzled together?
I don't think much of what I did here would be useful if you're using premade rooms and 3D.
if I had a gigantic map, how could I use this visibility system?
Godot is pretty awesome! Maybe you can do a more technical video on Godot itself
Can you PLEASE give the code on github.
im getting an err even though i did everything you did.(At least that's what I think)
for region in free_regions:
if region.intersects(region_to_remove):
removal_queue.append(region)
it says: Invalid type in function 'intersects' in base Rect2. cannot convert argument 1 from Array to Rect2.
please help
Late response, but it's up on GitHub now: github.com/Thoughtquake/dungeon-of-recycling
Anyone getting a error on the "add_room"(free_regions) line? It's in the
Func build_level(): lines. I have it written the same way. Even looked on his github at the code. It's all the same. Getting a (unused argument) error.
"Unused argument" ought to be just a warning that's safe to ignore.
Great tutorial, but I'm stuck on the visibility map. space_state.intersect_ray(player_center, test_point) ALWAYS returns an empty dictionary, so on the first run of update_visuals it always EVERY tile in visibility map to -1. I've checked my tilemap and the wall, stone and door tiles have collision shapes, which I verified with visible collision shapes in the debug menu. I tried adding occlusion shapes, but it made no difference.
I've read the documentation of the Physics2DDirectSpaceState, I've tried passing a collision_layer value into intersect_ray, but nothing works. Any ideas on how to troubleshoot further? It seems that intersect_ray either doesn't get the correct input somehow, OR somehow MY instance of it works differently, so returns different output for the same input.
Hey man did you end up working this out? I think I'm having a similar issue to you
EXAMPLE
var startRoom = rooms.front()
var playerX = startRoom.position.x + 1 + randi() % int(startRoom.size.x - 2)
var playerY = startRoom.position.y + 1 + randi() % int(startRoom.size.y - 2)
player_tile = Vector2(playerX, playerY)
yield(get_tree().create_timer(.2), "timeout")
call_deferred("update_sight")
Create a timer before you update the visuals. It doesn't work whenever the room is done building itself rightaway. Check out my comment on this video to see my full explanation
for me this worked the best:
func update_visuals():
player.position = player_tile * TILE_SIZE
yield(get_tree().create_timer(0.000001), "timeout")
#and the rest of the function is the same as in tutorial
Hello, if you could update this tutorial for Godot 4 I would appreciate it. But I understand it would be a lot of work.
How complex would multiplayer be to add to something like this?
Not as complex as that level generation code, that's for sure. Local splitscreen would be a cinch too.
I'm getting weird bugs where I don't actually spawn inside a room, and I cant move, hopefully I can figure it out but the more I go along more the errors I find, 19:11
okay I fixed movement now trying to figure out why my player is spawning outside of rooms instead of inside the rooms
OKAY I FINALLY FIXED THE CODE ALL ROOMS CONNECT AND MY PLAYER MOVES PERFECT, really ember to take breaks when having errors to easily find the solutions. my problem was that I had a lot of my x and y mixed up
watching it on .75x and still have to pause and rewind every 5 seconds take a fucking breath jesus christ
thank you!! I'm the 100th comment!!
random thing here - it's cool to see another person using Sublime text. have you also checked out Liclipse? And have you tried MS Visual Studio Code? I've been using Code for a while now on C++, Python, Lua, and even an industrial robot arm action-script (using python syntax highlighting which works alright).
No download link ? It's a bit of a pain to read the code on the video… Maybe you could at least copy it in a Pastebin ?
how could i add tweening to the movement??
Great tutorial - fast paced but not too fast and lots of explanation as you go!👍😀👍
Just FYI - I think it's pronounced "go-dot" (rhymes with robot).
Nah, it's either GOD-oh or goh-DOH depending on how you emphasise. Like in Waiting for Godot.
@@jplay9710 This is debated a lot; you're right that it's named after the French play and that's how I've been pronouncing it, but the creator of the Godot engine pronounced it differently (rhyming with robot) in a GDC talk. To be honest I'm sticking with the French pronunciation just because otherwise I expect a lot more people would try to correct me the other way.
you have a tutorial for rhythm games?
Sorry, but no. I'm sure you can find one somewhere though
@@Thoughtquake I don't find anywhere /=/=/=/=/=
where are the tiles?
This is amazing and I would not like to be rude but could you share the .GD? thanks
How do you get sprites or objects
opengameart.org is a good source
itch.io/game-assets another source
make them yourself is another great way. use gimp or krita and google some pixel art tutorials.
if you want to do pixel art; paint(dot)net is pretty good, it's tiny, fast and free.
for non pixel art stuff I use Krita.
have a look at mortmort on youtube, he makes pixel art tutorials and tip videos.
Do we make our own art for this
Go to opengameart and search dungeon crawl. They have the stone soup dungeon spritesheet with more tiles than you can ever use.
Personally I would always make my own art when following tutorials like this. Makes it much more fun and feels more like "your own creation". For this you really just need to open up paint or gimp and fire up a couple of 32x32 tiles, takes 5 minutes and you can always come back later and make them prettier.
First I was like: "Wow, Godot looks really intuitive and logical!"
Then he started coding...
Procedural generation looks complicated in any language. Especially when you didn't write it.
It is. lol
Hey there, Thoughtquake.
I've been watching your tutorial and following carefully, but I can't seem to figure out why the 'for i in range(num_rooms)' thing does not work for me. It says that 'for' is the unexpected token for some reason?
I have tried removing it (obviously didn't work lol) and rewriting that part and some parts behind it completely, but that did not work either.
Do you know the solution?
The exact thing that it says for me is 'error(58,1) Unexpected token: for:'
Thanks in advance.
That probably means you made a mistake on the previous line, like not closing parentheses, but it's impossible to tell without seeing the code.
@@Thoughtquake Thanks. I'll check that line out.
@@Thoughtquake I figured it out. Turns out I didn't even write an entire line of code! Thanks for the tutorial man, I have a ton of game ideas and thanks to your tutorial I can make it come true.
You mean the character is trash?
If you want to make a roguelike like a Mario maker, there is a game called `` Nanaka Mysterious Labyrinth Record ''
take-hisa.com/nanaka/
もしもローグライクをマリオメーカーのように作りたいなら「ナナカ 不思議の迷宮録」というゲームがあります
take-hisa.com/nanaka/
I feel like you move too fast, and your cursor is very hard to see. Please highlight it with your screen-capture software.
I mean I appreciate it but you don't explain what anything is or does...
There are other tutorials for that
Would have been nice but for two things. You go way too fast, and I have to pause and rewind way too much. Second, you should have supplied the art you made so we could follow along.
I was wondering where the art assets were, myself. Glad I am not crazy!
If you need someone to make 8 32x32 icons for you then I have important news - game development is not for you.
Too fast.
I gave up the moment i saw there was require to do bunch of coding. Might go and find other engine.
For visual scripting, Unreal may be a better choice
Maybe you would like clickteam fusion 2.5
So painful to watch... Are you intentionally using only one script?
It just seemed the easiest way to get it done quickly, and I didn't think about changing it until I was half-way through recording. Starting over would have taken a lot of time and I didn't think it would bother anyone as-is.
I hope you know comments like yours can really ruin someone's day. If it weren't for the larger number of people being positive and encouraging, I'd have given up on UA-cam completely by now. But that's what you want, isn't it?
I didn’t meant to hurt you. I am really sorry about that and I want to apologize. I really thought you did intentionally wrote the long code just for fun. I hope you don’t feel bad anymore. I will delete original comment if you want.
@@빵빵빵-m1o Maybe I misread your intent when you said it was "painful to watch". I get a lot of hateful comments and assumed you were just another person trying to insult my intelligence and discourage me from making videos.
then make your own tutorial and upload it you piece of shit
I got 5 mins in, and realized you didn't provide the art, not much of a tutorial if you can't follow along. Plus you go at light speed. This one's a dud
so what? make your own. i made mine in paint. works for the first time, doesn't have to be god level art. its good as long as it works for your game.
Poor pathfinding code(
What exactly is poor about it? It gets the job done perfectly fine
Talk faster.