How can I move the player from one tilemap to another?

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

Version: 3.1; Project Source

Hi folks. I’m working on a 2D grid-based game based on a prototype by GDquest. In the game the player can traverse a tilemap. I would also like the player to be able to move to other tilemaps. Some approaches I’ve seen of “connecting” tilemaps together simply have the entire game in one tilemap and move a Camera2D around, ala The Legend of Zelda. That is not what I want. I am trying to do something closer to Pokemon or other RPGs where, for example, the player can go inside a house and be transferred to the house’s unique interior.

One thread I found gives us a way to switch scenes back and forth. It stores the scenes in a dictionary in order to switch between them. I made an improvement that allows the changes in the scenes to persist. I detach the scene from the node tree and store it in the dictionary instead of destroying & recreating it. This allows the player to move things around in one map, go to a different map, and come back to the previous map and their changes will still be present.

Here is my project source. You can observe the behaviour above by pressing 1 and 2 to alternate between maps. Try pushing some blocks around and notice how they stay where you left them after switching between 1 and 2.

However, an important part of this mechanic is being able to move the player to the receiving tilemap/scene. I created a “Portal” class that attempts to solve this by detecting when the player collides with it and moving the player to a corresponding Portal object on the tilemap in the second scene. My logic is that I first detach the player from inside the first scene and save it. Then I detach the first scene (it’s saved in the dictionary). Then I attach the second/receiving scene to the SceneTree. Then I finally reattach the player to the second scene (which now becomes the current map). I also explained this in this reddit thread.

But for whatever reason, the Player won’t reattach to the second scene. When I try to do add_child it is not working. I can tell because I don’t see the Player in the Remote view in the editor after I go through the Portal, regardless of the Player’s coordinates on the screen. You can reproduce this by walking through the top of the level into the diamond shape (ie. the Portal). (If the game crashes, keep trying until it goes through).

I think that I’m not doing the add_child call correctly, or I am not doing the Node removals/reattaching correctly since my research on this problem suggested I use call_deferred, which did not work. This thread on add_child might be the issue I am having.

Any insight would be appreciated. If there is a better way to accomplish what I am doing please tell me. If I can solve this problem and complete this mechanic then I will distribute the solution in a tutorial or back to GDquest. I will also be sharing this Ask to the Godot/GDquest reddit and discord communities.

TL;DR: Download my project and please tell me why the Player isn’t being added to Level2.tscn when I try to add it as a child. The concerning code is in res:// and res://world/props/ The two levels are in res://world/levels

Thank you!

:bust_in_silhouette: Reply From: eons

Here Scene organization — Godot Engine (3.1) documentation in English, and in the “changing scenes” are some ideas of how to organize your scenes.

TL;DR, your scenes do no t need to be the main scene of the game, just put levels on a sub-node of your game, hide or remove from the tree when not needed.

In that case you can chose to keep important data outside of the player and re-initialize it on a new instance on the new tilemap, also the player can be a sibling of the tilemap (if can avoid being a child).

Otherwise, you will need some scene manager and data storage autoloaded nodes/scripts to maintain states between transitions.

All the “best practices” sections mention many things that can give you more ideas of how to adapt features to your design, or how to refactor your scenes to fit your needs.

Thanks for the reply. That documentation you linked was especially useful.

I could re-instance the Player in each level. But luckily I’ve managed to get my prototype working. I can move the same Player instance from level to level without having to recreate it. I’ll leave a breadcrumb trail of the sources I used to get to this point:

Scene organization — Godot Engine (3.1) documentation in English followed the link to…

Change scenes manually — Godot Engine (3.1) documentation in English Referring to this page I am using strategy 3 to change levels.

Then I was googling things like godot move node since I wanted to move the player to a different part of the SceneTree. I found this: How to reparent nodes with GDScript which reminded me that I need to remove the player as a child from the first level in order to add it to the second. Then I rewrote the method completely and used this to write the part that reparents the Player to the new level.

Finally, this thread Thread safe APIs — Godot Engine (3.1) documentation in English gave me the idea to add a liberal sprinkling of call_deferred in place of every regular add_child and remove_child in my script. After that it seems to be working now.

Here is the commit with this change. The most important code is inside the portal method of All that’s left to do is set the player’s position correctly in the receiving level.

If anybody has improvements to suggest then please have at it. Reading the Debugger it looks like there are still some set_owner shenanigans going on. Godot is a mystery.

When I have this prototype polished and cleaned up then I might present it.

Hugh Bagan | 2019-05-10 07:19

:bust_in_silhouette: Reply From: Skydome

I found this tutorial that I think will help you