|
|
|
 |
Reply From: |
HauntedWindow |
You might want to consider using an event bus. So your player damage system node will get your singleton “event bus” node. When they get hurt, you’ll make the event bus emit a “on_player_damage” signal. A node in your hearts scene will also get your “event bus” node and connect to its “on_player_damage” signal and play the proper animation. That way your player scene and your hearts scene don’t have to know anything about each-other.
So I watched the tutorial you linked and I’ve tried it, and I’m not entirely sure what I’m doing wrong. Here’s a walkthrough:
This is in the Slime enemy scene. At the top of the script I put
signal Slime_attacked(damage)
This is in the _physics_process(delta: float)
func of the Slime scene.
if $AttackRaycast1.is_colliding() or $AttackRaycast2.is_colliding():
$AnimationPlayer.play("Attack")
emit_signal("Slime_attacked", damage)
This is in the script for the root node of the level scene where the player, hearts and enemy instances are:
var health: int = 6
func _ready():
$Background/AnimationPlayer.play("GameHeart1Full")
$Background/AnimationPlayer.play("GameHeart2Full")
$Background/AnimationPlayer.play("GameHeart3Full")
$Background.connect("Slime_attacked",$Enemies/Slime1,"_on_Slime_attacked")
And this is the signal func here:
func _on_Slime_attacked():
print("Boo")
health= health -1
if health == 6:
$Background/AnimationPlayer.play("GameHeart1Full")
$Background/AnimationPlayer.play("GameHeart2Full")
$Background/AnimationPlayer.play("GameHeart3Full")
I really have no experience with this side of Godot so some extra help to finish this would be amazing 
BuddyGames | 2021-01-29 22:26
Ok, we basically have 5 scenes:
- The enemy slime scene
- The player scene
- The hearts scene
- The level scene that contains the enemy, the player, and the hearts
- The autoloaded event bus scene
Let’s go over what happens when the slime attacks:
When your slime attacks, you’ll use your raycast nodes to determine if they hit the player and if they did, you’ll get the Player’s collider:
var player_collider = null
if $AttackRaycast1.is_colliding():
player_collider = $AttackRaycast1.get_collider()
elif $AttackRaycast2.is_colliding():
player_collider = $AttackRaycast2.get_collider()
After that, you’ll want the slime to communicate directly with the player to let it know it’s been damaged. However, you’ll want to do this in a way that assumes very little about the node structure in the player scene. So we’ll use propagate_call so that any node inside the player scene that has a take_damage method will have that method called:
if player_collider != null:
player_collider.propagate_call("take_damage", [damage_amount])
OK, so inside your player scene you’ll make a node and call it something like player_health. That node will have a take_damage method that looks something like this:
func take_damage(amount):
health -= amount
$event_bus.emit_signal("on_player_damaged", health)
That event bus is an autoloaded scene that has a single node. The event bus will have a single node that has this in it:
signal on_player_damaged(new_health)
Your event bus acts a a global messaging system. Nodes can emit these “global” events by emitting them from the event bus. Nodes that need to receive these events connect to the signal on the event bus. This allows your player to notify your hearts that the player has been damaged without the hearts needing to know anything about the player. So your hearts will have some code that looks something like this:
_ready():
$event_bus.connect("on_player_damaged", self, "_on_player_damaged")
func _on_player_damaged(health):
play the heart animation
As your game develops, you’ll add more signals to the event bus as you need them.
HauntedWindow | 2021-01-31 20:10