How to handle transitioning between scenes in a metroidvania?

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

I am starting to work on a short metroidvania game, and I am not entirely sure how to approach transition between scenes. I want to have a connected world with multiple scenes, and each scene will have one or more exits connected to other scenes. (This is exactly how Hollow Knight works, for example).

To clarify, the behaviour I’m trying to get is this: Let’s say I have two scenes right next to one another - let’s call the left one A and the right one B. If the player walks to the right side of scene A, the scene will be switched and the player will appear on the left side of scene B.

I would really like to have an elegant solution to this so I can design my world and making changes to it somewhat easily. Thank you for your help!

:bust_in_silhouette: Reply From: Lopy

You could make yourself a Node2D that represents a “door” from one room to the next. If the player walks through one, they go to the corresponding room, at the door marked to lead where you came from.

There are a handful of 2D Nodes that you can use to have editor-only display, or you can simply make it run visible = false inside a _ready.

To set the room a door leads to, you can export a variable. The easy way is to export a String, but an enum would avoid typing errors:

var destination: String
tool # To allow _get_property_list to work in the editor

func _get_property_list() -> Array: # Allows to make custom exports
    return [{
            name = "destination",
            type = TYPE_STRING,
            hint = PROPERTY_HINT_ENUM,
            hint_string = list_rooms()
        }]

func list_rooms() -> String: # Simply lists the filenames in a folder
    var room_scene_folder := "res://"
    var directory := Directory.new()
    directory.open(room_scene_folder)
    directory.list_dir_begin(true)
    var rooms := ""
    var name := directory.get_next()
    while name:
        rooms += name
        name = directory.get_next()
        if name:
            rooms += ","
    return rooms

To convert the room name to a PackedScene simply get back the full path (room_scene_folder.plus_file(destination)), and call load on that.

To find back which door you “came through”, you can have them all register on _ready to an autoload, (MyAutoload.my_array.append(self)). And then teleport the player to it. Just make sure to clear the Array when a room is unloaded

To detect the player entering a door, you can use Area2D and have them press a button when colliding, or put two Areas, and detect when both are entered in short succession/the right order. The order would be a regular exported bool.

This is a great answer, thank you!

Azdrawee | 2021-07-23 10:48