Reputation: 13
Ok so I have an animator that plays a transition screen everytime my player goes to a different room. In this main room I have 4 Area2Ds that go to different scenes. For the animation change and transition I need to add a signal to the Area2D. However, if I add all four Area2Ds to the animation player's signal, the player teleports to every room till the last one connected. I was wondering if there was a work around for this or am I using the signals wrong.
code for changing rooms for Area2D:
extends Area2D
var entered = false
@export var room = ""
var animation_playing = false
@export var xPosition = 0
@export var yPosition = 0
var player
func _on_body_entered(body: PhysicsBody2D):
entered = true
player = body
func _on_body_exited(body):
entered = false
func _process(delta):
if entered == true and animation_playing == false:
var scene = get_parent()
if scene.has_method("playFadeOutTransition"):
animation_playing = true
scene.playFadeOutTransition()
func _on_transition_animation_finished(anim_name):
if anim_name == "fade_out":
var autoload = get_node("/root/Global")
autoload.playerStartPosition = Vector2(xPosition, yPosition)
get_tree().change_scene_to_file(room);
animation_playing = false
main scene script that is incharge of transitions:
extends Node2D
@export var fadeIn = false
func _ready():
$Transition/ColorRect.visible = false
if fadeIn == true:
$Transition/ColorRect.visible = true
playFadeInTransition()
func playFadeOutTransition():
$Transition.play("fade_out")
func playFadeInTransition():
$Transition.play("fade_in")
func _on_transition_animation_finished(_anim_name):
$Transition/ColorRect.visible = false
I tried using an autoload for saving the room I need to switch to, however, it gets overwritten every time since every area2d will be called when the animation finishes. I'm not sure what else to do.
Upvotes: 0
Views: 87
Reputation: 1729
All of your areas are connected to the same signal, waiting for the same animation to end. So every function will be called if that animation finishes.
There are two ways to fix that.
For the first option you have to remove the signals in the areas I assume you connected through the editor. The easiest way to do that would be by implementing a global event bus, but for the sake of text I will do it by passing the animation player directly to the area.
The code would look like this:
extends Area2D
var entered = false
@export var room = ""
var animation_playing = false
@export var xPosition = 0
@export var yPosition = 0
var player
var transition_animation_player : AnimationPlayer = null
# Called when the node enters the scene tree for the first time.
func _ready():
transition_animation_player = get_parent().get_node("Transistion")
func _on_body_entered(body: PhysicsBody2D):
entered = true
player = body
func _on_body_exited(body):
entered = false
func _process(delta):
if entered == true and animation_playing == false:
if transition_animation_player != null:
transition_animation_player.animation_finished.connect(_on_transition_animation_finished) # connect on play
animation_playing = true
transition_animation_player.play("fade_out")
func _on_transition_animation_finished(anim_name):
if anim_name == "fade_out":
transition_animation_player.animation_finished.disconnect(_on_transition_animation_finished) #disconnect signal when finished
var autoload = get_node("/root/Global")
autoload.playerStartPosition = Vector2(xPosition, yPosition)
get_tree().change_scene_to_file(room);
animation_playing = false
Here I get the animation_player on_ready
and connect the signals only if needed. The problem here is that it only works as long as only one signal is waiting for the fade_out animation.
The second option is to set a global variable. For example the room to enter. You already got a global script so lets say it contains a variable like this:
var room_to_enter = null
We leave the signals conntected as they are and set the value, when entering an area:
func _on_body_entered(body: PhysicsBody2D): entered = true var autoload = get_node("/root/Global") autoload.room_to_enter = room player = body
The process of triggering the animation stays the same, but now we have a second statement to check, if the animation finishes:
func _on_transition_animation_finished(anim_name):
var autoload = get_node("/root/Global")
if autoload.room_to_enter == room: #just do stuff if it's our room
if anim_name == "fade_out":
autoload.playerStartPosition = Vector2(xPosition, yPosition)
get_tree().change_scene_to_file(room);
animation_playing = false
Upvotes: 0