Implementing a Zelda-like top-down minimap?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ShingleBells

I want to make a top-down zelda-like game, and i want to give it a minimap similar to the older zelda games with a room-based minimap that gradually gets revealed to you as you explore. What’s the easiest way to go about this?

:bust_in_silhouette: Reply From: Zylann

If you make a Zelda game, I assume your game already has a concept of room-based map, so you should already be able to identify what a room is in your game (one room = one scene for example).

To make a minimap scene, you can iterate over the rooms in your game, lay them out in a tilemap where each room is a tile, and colour them differently by checking if you visited the room already.

This implies that you can associate a room with its position without having to load that room. How to do this is up to you.


One way is to have a data script in which you associate each room with its position on the map:

# map_layout_data.gd
const room_positions = {
    "start_village.tscn": Vector2(10, 10),
    "forest1.tscn": Vector2(11, 10),
    "forest2.tscn": Vector2(12, 10),
    "hermit_house.tscn": Vector2(12, 11)
}

And you can access this data anytime by writing this:

var layout = preload("map_layout_data.gd")
var pos = layout["start_village.tscn"]
# or
var pos = layout[current_room.filename.get_file()]

however if your game works already then that’s surely an information you have started to play with. However, if you have put that information inside the room scenes, it could be a good time to pick it out and place it in the same data script, so you won’t repeat yourself.


An alternative way is to use the minimap scene itself as an association, and use nodes instead of a tilemap with grid snapping:
Have one scene for your minimap which is always available (use a singleton or partially alter your scene), in which you place one “miniroom” per room. Then you can have a script on those minirooms which associates them with the real room (again, no need to instance all the rooms). And at the same time, you can use that minimap scene as the source of information about “which room is next to which room” so you know which to load at any time.

# miniroom.gd
var room = "start_village.tscn"

func get_grid_position():
    return Vector2(round(position.x), round(position.y))

;

# minimap.gd
var _grid = {}

func _ready():
    for i in get_child_count():
        var miniroom = get_child(i)
         _grid[miniroom.get_grid_position()] = miniroom

 func get_neighbor_miniroom(pos, dir):
    var npos = pos + dir
    npos.x = round(npos.x)
    npos.y = round(npos.y)
    return _grid[npos]

There are many variants to try, so i cannot say what is the easiest^^