Okay, I think I need something to hide secret areas from the player and reveal it to them when they approach it. I’ve lived without this mechanic for a while, placing secret areas a fair distance from the main game area, so that they’re not visible. But such distances make it difficult to place time-limited things within those secret areas, like the invulnerability power-up, since travelling back to the main area to use it would eat up into the player’s power-up time. I could add ways for the player to return to the main play area quickly, like doors, but that complicates the level geometry and I need to place them out of the way, like in the sky.
So, I’ll add a new element to do this. It will be an Area2D
node with an associated tile layer as a child. When the player enters the Area2D
, the tile layer is hidden away and the player can see the revealed secret. The player leaving the Area2D
will make the tile layer visible again.
Okay, the new SecretReveal
scene has been built. The root node is an Area2D
which takes, as children when added to the main scene, a CollisionShape2D
to act as the trigger space, and a tile layer to act as the tiles to hide/show. The tile layer needs to be in the foreground, which is Z Index 10 and with collision turned off, so that it’ll reveal the mid and background layers. The script simply tracks entering bodies (it monitors layer 2, which is dedicated to the player).
Now, the next question is how to fade the tile map in and out. I could just toggle the visibility but that’s way too jarring. What I hope to achieve is to add an animation player to SecretReveal
which will play a fade transition as the player enters or exits the Area2D
. But how to do that without using scripting? I rather use the primitives offered to me as I’m guessing they’ll be more efficient than throwing events around in GDSscript.
One possibility is the Modulate
option in the CanvasItem
properties. After quickly playing around with this in the editor, it looks like it’s possible to adjust the alpha channel on this property, and that would adjust the visibility of the tile layer:
So this looks viable. I’m actually glad that Area2D
has this property, despite not actually rendering itself in any way (outside of the editor) Let’s give it a try.
Okay, that works. Hooking it up to an animation player playing an animation that fades out and fades in the tiles when the player enters and leaves the trigger area works. It needs some improvement though. If the player were to enter and leave the target area quickly, the visibility would quickly “jump” from partially visible to fully visible. I suspect the reason for this is that the animation is always starting from the start.
One technique I used in the past is to preserve the current timestamp of the animation when I change it. But the animations here are using non-linear easing as it makes for a better transition.
So what I’ll try is a single animation that will be played forwards and backwards. When there’s a need to play the animation, the logic will detect whether the animation player is currently playing, and will resume playback from it’s current position in the desired direction.
Okay, so this is what I settled with:
func _on_body_entered(body: Node2D) -> void:
candidate_body = body
if animation_player.is_playing():
animation_player.play_section("reveal_secret", \
animation_player.current_animation_position)
else:
animation_player.play("reveal_secret")
func _on_body_exited(body: Node2D) -> void:
if body == candidate_body:
candidate_body = null
if animation_player.is_playing():
animation_player.play_section("reveal_secret", 0.0, \
animation_player.current_animation_position, -1, -1.0, true)
else:
animation_player.play_backwards("reveal_secret")
What I’m doing is when the player enters the trigger space, I’ll play the “reveal secret” animation, either from the start or from the current position, depending if the animation player is playing. If the player leaves the trigger space, and the animation player is not playing, I’ll play the “reveal secret” in reverse from the end. When it is playing, I do something similar but I need to set the end position to the current animation position, rather than the start position. I’m guessing the animation player will take the initial position as the end when it’s playing in reverse, which makes sense.
Here’s how the transition looks now:
Much smoother.
Now to try it out in level 3-1. And yeah, this is a much better way to do secrets. I can build them close to the play area and the player no longer needs to navigate them blindly, or walk a million miles just to get to the bonus. I won’t overdo it though. I’m going to keep some of the large secrets that are naturally out of the way as they were. The player will need to react fast to enter them so I want to make sure they have the opportunity to see them.
I am wondering whether to merge this with the “You found a secret” trigger, but I think I’ll keep them separate for now.