Skip to content

Conversation

@manuq
Copy link
Collaborator

@manuq manuq commented Oct 17, 2025

When called, wait for all particles to finish and then queue free.

This can be a callback of an Area2D body_entered signal.

This allows a scene to have with multiple Void enemies, each one chasing the player after the other. The player has to run (or walk!) from the Area2D that triggers the chasing to the Area2D that defeats the enemy.

@manuq manuq requested a review from a team as a code owner October 17, 2025 15:02
@wjt
Copy link
Member

wjt commented Oct 17, 2025

That is why the Node2D argument is needed.

Actually it's not, as I discovered in #1282 (comment) you can configure a signal connection to discard arguments of the signal that the receiving method doesn't want

@github-actions
Copy link

Play this branch at https://endlessm.github.io/threadbare/branches/endlessm/void-enemy-defeat.

(This launches the game from the start, not directly at the change(s) in this pull request.)

@manuq
Copy link
Collaborator Author

manuq commented Oct 17, 2025

That is why the Node2D argument is needed.

Actually it's not, as I discovered in #1282 (comment) you can configure a signal connection to discard arguments of the signal that the receiving method doesn't want

Ah great! I'll use that instead.

@manuq manuq force-pushed the void-enemy-defeat branch from 6b1824c to 425bda8 Compare October 17, 2025 15:11
Comment on lines 95 to 98
for particles: GPUParticles2D in get_children().filter(
func(c: Node) -> bool: return c is GPUParticles2D
):
await particles.finished
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might work in practice but in theory it won't work as you expect. Suppose you have 2 GPUParticles2D child nodes, A and B. Suppose they are in the scene tree in that order. But suppose B emits finished before A. This loop will first await A.finished, and then await B.finished which will never come.

In practice I think it works because particles are will emit finished in the order that they appear in the scene tree.

I think a better approach would be to do this in _emit_particles:

func _emit_particle() -> void:
    _live_particles += 1

    # current body

    _live_particles -= 1
    if state == DEFEATED and _live_particles == 0:
        queue_free()

And then in this function, replace this loop with:

if _live_particles == 0:
    queue_free()
# else wait for `_emit_particles` to free this node after all particles are finished.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a very good point, I was in doubt and since it worked in practice, I moved on. While doing this I checked an addon: https://godotengine.org/asset-library/asset/3592

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find - I was wondering how hard it would be to write that the other day!

When called, wait for all particles to finish and then queue free.

This can be a callback of an Area2D body_entered signal.

Co-authored-by: Will Thompson <wjt@endlessaccess.org>
@manuq manuq force-pushed the void-enemy-defeat branch from 425bda8 to 4b26a7d Compare October 17, 2025 17:17
@manuq manuq requested a review from wjt October 17, 2025 17:19
@wjt wjt merged commit 34992ef into main Oct 17, 2025
9 checks passed
@wjt wjt deleted the void-enemy-defeat branch October 17, 2025 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants