Godot Version
Godot 4.3
Preliminary
I’m trying to develop a 2D top-down game that features echolocation-like mechanic, where a button press reveals part of the map or details of the map in a circle that gradually expands and fade away. GIF below.
To work with this, I used the following setup more or less:
├── TrueMapLayer (Node2D)
│ └── LevelMapLayer (TileMapLayer, the one revealed on button press)
├── BackBufferCopy
│ ├── FakeMapLayer (TileMapLayer, the one always visible to player)
│ └── WaveManager (Node2D)
│ └── Waves (Sprite2D with shader, instantiated in runtime)
└── Player (CharacterBody2D, Sprite2D, AnimationPlayer, CollisionShape2D)
└── Camera2D
The Waves
node has a ShaderMaterial with a shader script that takes the texture from BackBufferCopy, and it uses a white circle PNG file as a sprite. Kind of like a masking. The scale change and fade is being Tween-ed.
Question
It’s working just fine now, but I thought of making tiles that can overlap the player while also only revealed in the circle. For example, walls on the bottom side of the room or objects placed in the floor. If the player is below those in the 2D space, the player sprite appears in front of the objects, and if the player is above those, the player sprite appears behind.
To achieve this, I tried a couple approaches which got nowhere:
-
I thought of using two separate TileMapLayers, one for Floor and one for Environment. If I want to achieve that, the setup has to be something like:
├── TrueFloor (TileMapLayer) ├── Player └── TrueEnvironment (TileMapLayer)
This is necessary so that the TrueEnvironment will always be in front of the player and able to be Y-sorted. But I don’t think this would be feasible for the BackBufferCopy setup. While the Floor and Environment can be revealed inside the circle, the
FakeMapLayer
would just cover the Player node and I wouldn’t be able to see the Player node.In other words, I need the player to be in front of BackBufferCopy so that the player is always visible, but it doesn’t seem possible since the player also has to be in between the map layers while the map layers are behind BackBufferCopy.
-
I thought of using the same TileMap and play around with the Z-index for different tiles. I tried this setup:
Floor tile -> z-index = 0 Player tile -> z-index = 1 Environment tile -> z-index = 2
This will still use the BackBufferCopy setup as well. But there’s no possible Z-index value for the FakeMapLayer. If I set it to 2 or 3, the Player node will be hidden behind it as well. If I set it to 0 or 1, the Environment tile would be visible even without the circle.
-
I also thought of using the same TileMapLayer and play around with the Y-sort for different tiles. But this is not feasible as well since enabling Y-sort on the TileMap will make all the tiles have Y-sort enabled too, including the floor. If I understand correctly, the Player node would have to be under a node that has Y-sort enabled too and has to be a sibling of the TileMap with Y-sort enabled. (I’m not sure about this though, please CMIIW).
EDIT: I tried this approach again by enabling Y-sort on the root node, but only enabling it on the true map and player child nodes. I did a workaround for the floor tiles by setting their Y-sort origin to -32. It works pretty well without the FakeMapLayer, but with it, only the true map tiles above the Y-axis is hidden behind the fake map. Even the player is also behind the fake map. The true map tiles below Y-axis is always visible, and this is not intentional. Adjusting the Z-index, or adjusting the entire map to be above or below Y-axis doesn’t work too.
I’m clueless here, is there any other approach I can try? The ones without BackBufferCopy would be okay too.
Thank you in advance. This is my first forum post, apologies for any mistakes.