Randomly Generated Dungeons in Godot Part 2 – Isometric

You can click here to read part 1

Last time I touched this project (almost a year ago, ouch) we got the drunken walk algorithm working inside of the Godot game engine. Now we are going to continue with the project and spawn in walls and a player.

Because it had been so long I went and tried to follow my own tutorial, to get back up to speed, and found it hard to follow. So I have gone back and added some details that I felt that it was lacking. It should be easier to follow now.

I have been on a bit of an Isometric kick so I thought it would be cool to get this random map generation to work in an isometric perspective. Like last time, the sprites that I used can be downloaded here

Just like with the isometric dungeons in Gamemaker Studio, we don’t need walls on all 4 sides of the floor, only two of them. So at the end of our _generate_map() function we can run a nested for loop, checking for ground tiles and flag the tiles above and to the left as walls.

for x in room_size.x:
	for y in room_size.y:
		if get_cell(x, y) == GROUND:
			if get_cell(x, y-1) == VOID:
				set_cell(x, y-1, WALL);
			if get_cell(x-1, y) == VOID:
				set_cell(x-1, y, WALL);

This step alone will not flag the walls because the tilemap is full of null values and not VOID so these if statements will not resolve to true. At the beginning of _generate_map() we need another for loop that sets all of the tiles as void.

for x in room_size.x:
	for y in room_size.y:
		set_cell(x, y, VOID);

Now when we run the scene, it should flag all of the walls. What you may notice is that floor tiles right at the edge of the scene will not have any walls, and to fix that you will just need to update the clamps from 0 and room_size.x/y -1 to 1 and room_size.x/y -2. This creates a 1 tile border around the edge of the map that can be dedicated to spawning in walls.

2D Random Walk with walls spawning in

Next we need to go to the editor and change the tilemap mode from square to isometric and update the sprites that we are using. You can either add my sprites or make your own.

If you do decide to make your own sprites the floor tile needs to be wider than it is tall. A good ratio is 64 pixels wide and 32 pixels tall. If You can make your floor 34 pixels tall to give it a little bit of thickness at the edges (You will see what I mean when we are done).

Clicking on the TileMap Node will display its inspector information on the right hand side of the window. Using the Mode drop down, select isometric instead of square, update the cell size from 32 by 32 to 64 by 32 and using the Tile Set drop down select New Tile Set.

When we click on the New Tile Set, the window at the bottom of the screen will update. Drag your new tile set sprite into the filesystem window and then add your new sprite to the tile set selector. My isometric sprites have a little bit of white space in between the tiles so we need to modify the step to be 64 by 97 and add a separation of 2 between the tiles and an offset of 1 like this.

A better quality video can be located here, Set the snap offset to 1 instead of 0

We need to add collision to the void and wall tiles that matches the shape of the floor. You will probably need to play with the snap options to move the grid lines so that it lines up properly.

I set the snap step to 32 by 16 and the offset at 5 to set the collision for the wall, and 1 to set the collision for the void space. You don’t need to worry about the little bit of the wall that is below the collision, the floor is going to draw over that.

If you have done everything properly when you execute the scene, it should be drawing the map in an isometric perspective, but some of your map may be off screen.

With the map rendering in an isometric perspective we are ready to add a player character and a camera so that we can explore the map. You will need to change the game window from 1024 by 1024 to something more appropriate. I picked 960 by 540.

To make our player we need to make a new scene. In the new scene menu, select other node and add a KinematicBody2D as the root node, add the player character sprite to your project and then drag the player sprite into the scene, and add a Camera2D and CollisionPolygon2D as child nodes to the Kinematic Body. The feet of the player sprite should be lined up with the horizontal pink line in the scene, consider that the floor.

The collision box on the CollisionPolygon should be in an isometric shape just like the tiles. It only needs to have 4 points. You can set them at the values in the screenshot below, and you need to check the “Current” flag on the camera2d node so that the camera will follow the player.

The KinematicBody2d node is going to need a script attached so we can listen for input and move the player. We assign a speed value to the player, and inside of _physics_process(delta): we listen for keystrokes and move the object based off of our speed value. The finished script looks something like this

extends KinematicBody2D

# Declare member variables here. Examples:
export (float) var spd = 120;

# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
	var motion = Vector2.ZERO;
	
	if (Input.is_action_pressed("ui_up")):
		motion += Vector2.UP;
	if (Input.is_action_pressed("ui_down")):
		motion += Vector2.DOWN;
	if (Input.is_action_pressed("ui_right")):
		motion += Vector2.RIGHT;
	if (Input.is_action_pressed("ui_left")):
		motion += Vector2.LEFT;
		
	motion = motion.normalized();
	motion *= spd;
	move_and_slide(motion);

Finally you can add the player scene as a child of the tilemap simply by dragging the player scene on top of the tilemap in the editor.

If you were to run the game at this point, you would notice that the player does not spawn inside of the map, and you are unable to move. We need to add 1 more line of code to the _generate_map() function of the tilemap script which moves the player inside of the tilemap.

$KinematicBody2D.position = map_to_world(room_size / 2);

With that one line of code added, when you execute the game, the player should be moved onto the very first tile that was flagged as a floor, and you should be able to move around the map, and collide with the walls.

Depth doesn’t work yet, so the player will always render above the walls, but as you can see, the player is able to move around the map, collide with the walls and the void space. We have set up the beginnings of a 2d Isometric game in the GODOT engine.

You can click here to read part 3

Until Next Time
– Steven

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.