In Player.gd change your ready function from:
func _ready():
stats.connect("no_health", self, "queue_free")
screen_size = get_viewport_rect().size
hide()
to
func _ready():
stats.connect("no_health", self, "_on_Stats_no_health")
screen_size = get_viewport_rect().size
hide()
This connects the "no_health"
signal emitted from stats to the "_on_stats_no_health()"
function rather than the "queue_free()"
function. So essentially what's happening is when stats emits the signal "no_health"
the Player object picks it up and calls self._on_Stats_no_health()
which goes on to call get_parent().game_over()
. When Player.gd calls get_parent()
, it receives your Main Node in your scene tree (top left), because Player is a child of Main. Hope that helps explain what's going on under the hood.