Hi, I’m new to Godot and am trying to make a simple game right now. Here is the issue I’m faced with:
My demo consists of two lanterns, both of which have already been scripted to light up when the player walks past it. They also come from the same scene, so they consist of the same properties.
However, when the player approaches the second lantern, I want the first one to be signaled to deactivate (turn off).
I’ll be using these as checkpoints throughout the game, so I want only one indicator at a time.
This also means that I have a constraint to make the code recyclable since I will be using an undefined number of lanterns, so I don’t want to make each lantern call each other or something like that.
Through the _on_body_entered() signal, I want to emit to all other lanterns _on_signal_off(), however the message never gets emitted to them. Do you have any ideas on how I should fix this? Thank you.
If there is only ever going to be 1 lantern active then I would go up one level (to the game scene or what have you) and add a variable active_lantern.
Connect the each lanterns _on_body_entered() to a function in the higher level code/scene.
When the character passes a lantern call down to a function in lantern (active_lantern.set_off()) and change active_lantern to the newly passed lantern.
There isn’t a need to shut off a bunch of lanterns that are already off.
The implementation changes if you need more lanterns active at the same time as you will have to use an array of active lanterns.
Seems like your _on_body_enter will only emit signalOff once since you never set passed back to false, try emit signalOff either way and handle the animation inside the _on_signal_off function with different active and passed combination, and by the way, you probably need the body_exit signal.
I had intended for on_body_entered() to be called only once, since as the game progresses I don’t want players backtracking to a previous checkpoint. That is where the PASSED variable comes in.
As for the body_exit() signal, I want the lantern to stay active as long as the player has not approached a new lantern. If the player falls and dies, I intend for them to return to the active lantern.
I believe the current issue right now is that the lantern that gets passed cannot emit the on_signal_off() to other lanterns. That is what I am trying to accomplish right now.
Thanks for the help though, I appreciate it very much.
But that doesn’t answer the question, from your script you’re only connecting the proper lantern signal, but you need to listen the other lanterns signal.
I’m thinking you misundertand how the signals work so lets try check that. You have two lantern objects, the one on the left and the other on right. From your script you’re only listering from their proper signals, example: If i touch the left lantern, this lantern will emit her signal, but only the left lantern will listen because you didn’t connect the left lantern signal in the right lantern.
In that case, is there a way to connect them? The script I showed above applies to both lanterns. Also, if I add a third or a fourth lantern, will I have to manually connect all of them together?
You had to get a reference of every latern you have and manually connect them by code or in editor.
Yes
I think for you case groups will be much more simpler for you, with that you can have n lanterns, everything will work without any code change:
var ACTIVE = false
var PASSED = false
# Not needed
#signal signalOff
func _ready() -> void:
# Not needed
#connect("signalOff", _on_signal_off)
# Add the node to a group called "lantern"
add_to_group("lantern")
func _on_body_entered(body: Node2D) -> void:
if not ACTIVE and not PASSED:
$animatedSprite2D.play("glow")
ACTIVE = true
PASSED = true
# Call the function "turn_light_off" in every node
# inside the "lantern" group, pass the proper node
# as argument for use when calling the function.
get_tree().call_group("lantern", "turn_light_off", self)
func turn_light_off(p_lantern_caller) -> void:
# Don't turn the proper lantern off, only the others
if p_lantern_caller == self:
return
if ACTIVE and PASSED:
$animatedSprite2D.play_backwards("glow")
ACTIVE = false
Thank you very much, this was what I was looking for.
May I ask though, is there a way I can access the properties of the ACTIVE lantern? Because there is more that I want to do with it than turning the lights on.
Yes, use get_tree().get_nodes_in_group("lantern") to get a list with all nodes inside the “lantern” group and after that you can search which node you want to modify using a for loop and checking if ACTIVE is true.