TileMap in Godot – Complete Guide

Tile-based games are a staple in the game development world, offering a unique charm with their distinct, grid-aligned aesthetics and straightforward design mechanics. Whether you’re aspiring to create a retro-style RPG, a strategic top-down shooter, or a bustling city builder, understanding how to implement a tilemap can be a critical step in your journey. This tutorial will guide you through the TileMap class in Godot 4, covering the fundamentals and providing practical examples to help you learn how to create and manage tile-based maps effectively.

What is TileMap?

A TileMap is a Node2D that facilitates the construction of 2D tile-based maps within the Godot Engine. It uses a TileSet, which is a collection of tiles, to create these maps. Tiles are small, reusable images that can be pieced together to form more complex scenes or landscapes on your game’s grid. Through the TileMap node, you can add, remove, and modify tiles, making it a powerful tool for both level designers and developers.

What is it for?

TileMaps serve various purposes in game development:

  • Creating detailed game worlds with ease.
  • Optimizing rendering performance through the use of tilesets.
  • Facilitating level design through a visual and grid-based approach.
  • Enabling collision detection and character movement on grid-aligned paths.

By using TileMaps, you can construct intricate game levels based on tiles which are typically more efficient to render and manage compared to individually placing each game object.

Why Should I Learn It?

Learning how to effectively use TileMaps is an investment in your game development skill set. Here’s why:

  • Efficiency: TileMaps streamline the game development process by allowing you to rapidly prototype and iterate on level designs.
  • Flexibility: Well-versed knowledge in TileMaps allows you to customize and extend your game maps to fit various game genres and styles.
  • Fundamental Skill: Mastery of TileMaps is a foundational skill for 2D game development and it is beneficial for anyone looking to create grid-based games.

The understanding and application of TileMaps will not only enhance the visual quality of your games but also improve the way you approach map development, collisions, and interactivity within a 2D space. Let’s embark on this learning adventure and unlock the potential of TileMaps in Godot 4.

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Creating a New TileMap and TileSet

Before we get started with the fun part of painting tiles onto our TileMap, we need to set up both a TileMap node and a TileSet resource in our Godot 4 project.

var tilemap = TileMap.new()
add_child(tilemap)
var tileset = TileSet.new()
tilemap.tile_set = tileset

Now that our TileMap node and TileSet resource are initialised, we can begin adding tiles to our TileSet. For example, suppose you want to create a simple grass tile:

var grass_texture = preload("res://textures/grass_tile.png")
var grass_id = tileset.get_last_unused_tile_id()
tileset.create_tile(grass_id)
tileset.tile_set_texture(grass_id, grass_texture)

The code above preloads the grass tile texture, generates a new tile identifier, creates a new tile with this identifier, and finally sets the texture of the new tile to be our grass texture.

Painting Tiles onto the TileMap

With our TileSet prepared with at least one tile, we can start painting tiles onto our TileMap. Here’s an example of how to paint a single grass tile at a specified grid location:

tilemap.set_cellv(Vector2(10, 5), grass_id)

But, to paint multiple tiles at once, we could use a loop:

for x in range(20):
    for y in range(15):
        tilemap.set_cellv(Vector2(x, y), grass_id)

The above code would fill a 20×15 area with grass tiles.

Erasing Tiles from the TileMap

There might be scenarios where you need to erase a tile from the TileMap. In Godot 4, you can accomplish this like so:

tilemap.set_cellv(Vector2(10, 5), -1)

This code would erase the tile at the grid location (10, 5).

Managing TileMap Collisions

It’s also quite simple to add collision to a tile. You can achieve this by creating a collision shape for the tile in the TileSet:

var tile_shape = RectangleShape2D.new()
tile_shape.extents = Vector2(16, 16)
tileset.tile_set_shape(grass_id, 0, tile_shape)

This assigns a rectangular collision shape to the grass tile we created earlier. The ‘0’ in the code specifies the shape’s index, in case the tile has multiple collision shapes.

Using Autotile for Seamless Level Design

Godot’s powerful Autotile feature allows for seamless level designs, making it easier to paint intricate tile patterns. Here’s how to set up an Autotile:

var autotile_texture = preload("res://textures/autotile.png")
var autotile_id = tileset.get_last_unused_tile_id()
tileset.create_tile(autotile_id)
tileset.tile_set_texture(autotile_id, autotile_texture)
tileset.autotile_set_spacing(autotile_id, 1)
tileset.tile_set_autotile(autotile_id, autotile_texture, Vector2(3, 3), Vector2(0, 0))

This snippet preloads an autotile texture, creates a new tile for it, and provides the necessary configuration for autotiling, which includes the spacing between tiles and the subdivision of the texture into a 3×3 grid, corresponding to the possible connections in eight directions (up, down, left, right, and the four diagonals).

Now, your TileMap is equipped with a basic grass tile and an Autotile, you have the skills to start painting your world and experimenting with various patterns and designs that will make your levels engaging and diverse!As you grow more comfortable with painting and erasing tiles, you might want to explore more advanced features of the TileMap class. Godot 4 provides several functionalities that can help enhance the look and feel of your game. Let’s delve into some of these.

One key feature is the ability to use different layers within your TileMap for organizing various elements of your game environment. For instance, you might have a background layer, a layer for the main play area, and a foreground layer for elements that appear above the player. Here’s how you can implement layers:

tilemap.create_layer("Background")
tilemap.create_layer("Foreground")

To specify which layer you want to paint on, you can use the `current_layer` property:

tilemap.current_layer = tilemap.get_layer_index("Foreground")
tilemap.set_cellv(Vector2(10, 5), grass_id)

This code sets the current layer to “Foreground” and then paints a grass tile at the location (10, 5) on this layer.

Another handy feature is manipulating the Z-index of your tiles. This can be used to ensure that certain tiles always render above or below others, which is particularly useful for creating overlapping elements:

tileset.tile_set_z_index(grass_id, 1)

The above line sets the Z-index of our grass tile to ‘1’, which would place it above tiles with a Z-index of ‘0’ or less.

Animations within your TileMap can add a dynamic element to your game world:

tileset.tile_set_animation(autotile_id, true)
tileset.tile_set_animation_frames(autotile_id, [frame_0, frame_1, frame_2])
tileset.tile_set_animation_speed(autotile_id, 5)

In this code snippet, we turn on animation for our Autotile, provide an array of animation frames, and set the animation speed. This can be great for animating water, fire, or other environmental effects.

You may also want to flip or rotate tiles for variety without creating new tiles:

tilemap.set_cellv(Vector2(10, 5), grass_id, false, true) // Flips the tile horizontally
tilemap.set_cellv(Vector2(15, 5), grass_id, true)            // Flips the tile vertically
tilemap.set_cellv(Vector2(20, 5), grass_id, false, false, true) // Rotates the tile 90 degrees clockwise

Here we flip the same grass tile horizontally and vertically, and we also rotate it by 90 degrees.

For managing large tile sets, Godot offers atlases. These are like big texture pages where many tiles are packed together. Using an atlas can improve performance because it reduces the number of texture changes the GPU has to perform. Here’s an example of how you might create a tile atlas in your TileSet:

var atlas_texture = preload("res://textures/tile_atlas.png")
var atlas_id = tileset.get_last_unused_tile_id()
tileset.create_tile(atlas_id)
tileset.tile_set_texture(atlas_id, atlas_texture)

// Define a region of the atlas for a particular tile
tileset.autotile_set_subtile_size(atlas_id, Vector2(32, 32))
tileset.region_set_tile(atlas_id, 0, Rect2(0, 0, 32, 32)) // The region for our tile

In the example, we’re setting up a 32×32 region of our atlas to represent an individual tile.

Using these features and code snippets, you can begin building more complex and visually appealing tile-based environments in Godot 4. Experimenting with layers, Z-indexing, animations, flips, rotations, and atlases will give you the flexibility and tools required to create truly immersive game worlds.As your game world becomes more intricate, managing collisions and their impact on player experience becomes essential. Godot’s latest iteration offers you effortless yet powerful mechanisms for handling collisions within a TileMap. Let’s enhance our existing tiles with collision shapes, which will determine how the player and other objects interact with the tiles:

// Define collision for a tile
var collision_shape = RectangleShape2D.new()
collision_shape.extents = Vector2(16, 16)
tileset.tile_set_shape(grass_id, 0, collision_shape)

This example adds a square collision shape to our grass tile. The `extents` parameter specifies the size of the collision, corresponding to half the width and half the height of the collision rectangle.

Apart from static collisions, you might want to trigger certain events or effects when the player reaches specific areas. Godot offers collision layers and masks for this purpose:

// Set the collision layer and mask
tileset.tile_set_collision_layer(grass_id, 1)   // Set the tile to be on the first collision layer
tileset.tile_set_collision_mask(grass_id, 1)    // Set the tile to also check for collisions on the first layer

In this code, we’ve assigned the collision layer and mask to 1 for our grass tile. This means the tile will interact with other objects that are on or collide with the first layer.

Godot’s TileMap also integrates seamlessly with the engine’s Navigation2D node, enabling pathfinding and movement across the tile-based terrain:

// Configure a navigation polygon for tile-based pathfinding
var nav_poly = NavigationPolygon.new()
nav_poly.add_outline(PoolVector2Array([Vector2(0, 0), Vector2(0, 32), Vector2(32, 32), Vector2(32, 0)]))
nav_poly.make_polygons_from_outlines()

tileset.tile_set_navigation_polygon(grass_id, nav_poly)

We create a navigation polygon that matches the shape of our tile, eventually binding it to our grass tile. This would allow characters to use the tile for navigation when determining paths.

Now, let us consider the implementation of Occlusion in a TileMap, which can be used to create a sense of depth and height by blocking light sources:

// Set up an occluder for a tile
var occluder = OccluderPolygon2D.new()
occluder.set_shape(PoolVector2Array([Vector2(0,0), Vector2(32, 0), Vector2(32, 32), Vector2(0, 32)]))

tileset.tile_set_light_occluder(grass_id, occluder)

Here we configure a light occluder for our grass tile. This effectively tells Godot’s lighting system that the tile blocks light, casting a shadow and adding depth to our game.

Animations can also be adjusted at runtime, which is handy for changing environments or interactive scenes:

// Change the animation speed or disable it based on in-game events
tileset.tile_set_animation_speed(grass_id, 0) // Freeze the animation
tileset.tile_set_animation_speed(grass_id, 10) // Speed up the animation

In these lines of code, we modify the animation speed of our already animated tile, from freezing it at a speed of 0 to increasing it for a faster cycle.

Lastly, your TileMap can also adjust to different tile shapes, such as hexagonal or isometric, which can offer a new perspective and present new design challenges and opportunities:

// Changing the TileMap mode to work with isometric tiles
tilemap.mode = TileMap.MODE_ISOMETRIC

By changing the `mode` property of our TileMap, we redefine how our tiles are orientated and drawn, switching from a traditional square grid to an isometric layout.

These additional code samples and suggestions open up new horizons in the versatility and functionality of your 2D game’s tile-based environments. By tapping into collision layers, navigation, occlusion properties, runtime animation control, and different tile layouts, you stand equipped to delve into deeper mechanics that can make your games stand out.

Where to Go Next

Mastering the TileMap features in Godot 4 is just the beginning. If you’re excited about continuing your game development journey, our Godot Game Development Mini-Degree is an excellent next step. With this comprehensive collection of courses, you’ll dive into the vast world of Godot 4, exploring topics from the very basics to more advanced techniques that will embolden your game-building skills.

Whether you’re interested in crafting intricate 2D platformers, designing sprawling 3D environments, or learning the nuances of the GDScript programming language, our curriculum is carefully tailored to expand your knowledge landscape. Construct your own games, create compelling gameplay mechanics, and join a thriving community of developers on the same path.

For a broader view of what we have to offer, check out our robust spectrum of Godot courses. Our courses are designed to be flexible, allowing you to learn at your own pace, anytime, anywhere. Embrace the opportunity to level up your game development expertise with Zenva, where you can go from beginner to professional in one of the most dynamic industries today.

Conclusion

As we’ve journeyed through the fundamental aspects and code snippets of the TileMap class in Godot 4, it’s clear that the road to becoming a proficient game developer is both thrilling and filled with endless possibilities. With the knowledge you’ve gleaned here, you’re well on your way to building worlds that resonate with players, filled with intricate details, and ripe for exploration. Remember, what you’ve learned is just a fragment of what Godot offers, and there’s so much more awaiting you as you continue to grow.

Join us at Zenva to further this adventure, and let’s transform your passion for game creation into a reality. With each tutorial you complete, each line of code you write, and each challenge you overcome, you’ll not only enhance your skills but also imprint your unique mark upon the gaming landscape. So why wait? Start creating, learning, and shaping your game development future today!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.