Correct Way to Trigger “Hit” on Enemies at Point

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By BeepBoop

I have a top down game where a separate process sends “explosions” at random locations. I receive the x, y coordinates of the explosion origin and I need to destroy anything within a certain radius of the explosion origin. I’m very new to godot so trying to understand the correct way to implement this?

My initial idea was to create a circular Area2D centered on the given coordinates, call get_overlapping_bodies to get a list of destroyable things (they’ll all be an Enemy which is RigidBody2D) and then trigger their “hit” function. And finally remove the created Explosion. Is this a good approach or should I be looking at the body entered signal? There’ll be about 20-30 enemies on the screen at any one time of which 0-N could be in the explosion area

:bust_in_silhouette: Reply From: SabrinaAsimov

Hello ! Perhaps this is a very newby answer and I apologize in advance but reading official documentation about Area2D it says:

Array get_overlapping_areas ( ) const

Returns a list of intersecting Area2Ds. For performance reasons (collisions are all processed at the same time) this list is modified once during the physics step, not immediately after objects are moved. Consider using signals instead.

Description of Area2D Methods Godot Documentation Link

So, according to Godot Documentation you could emit a signal triggering a hit() function in the enemys that are in the explosion area

I wanted to try your approach and I made a very simple test and now I realize what the problem might be. I created some “radar” node (An Area2d with a circular CollisionShape emulating its detection radius and some enemies. I manually put some of this enemies in a World Scene containig also the radar. Everyting is fine…but…the hit() function not only affects the enemis inside the radar, but also the rest of them, even if they are far away ! I´ll keep testing and I´ll come back !

SabrinaAsimov | 2021-09-10 18:58

I´m back again ! I think I have a little solution !

I have a World Scene that contains instances of Monster Scenes, some instances of Friend Scenes and the Radar that detects enemys. Radar does nothing with Friends but kills enemies after 3 seconds they enter in Radar radious:

First, the Radar Script:

    extends Area2D


signal enemy_in_range


# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.


func _on_Radar_body_entered(body):
	if body.is_in_group("EnemiesGroup"):
		# Body is passed as an argument of the function, body is the id of the detected body
		emit_signal("enemy_in_range",body)

Now the Enemy Script:

extends RigidBody2D


# Called when the node enters the scene tree for the first time.
func _ready():
	add_to_group("EnemiesGroup",false)
	#Reference to Radar Node, I dont like this, If something changes, this code will break, but for now,it works
	var radar = get_node("/root/World/Radar") 
	radar.connect("enemy_in_range",self,"im_under_attack")



#This function change the color to red if enemy is detected by Radar and deletes it after 3 seconds if is inside radar area. Body is the instance id that we get in func _on_Radar_body_entered

func im_under_attack(body):
	if body == self:
		print ("Oh no !! The radar will kill me !!!")	
		modulate = Color.red
	#A timer is created, after 3 second, the tresppaser is destroyed
		yield(get_tree().create_timer(3), "timeout")
		queue_free()

Hope someone find it useful. Good luck !

SabrinaAsimov | 2021-09-10 23:03

Thanks!! I ended up going for a very similar approach, using the explosion body entered signal and checking what group the body was in. If it’s in the right group I call an “explode” method on the body that triggered the body entered handler because there can be more than one explosion on the screen but I’m principle it’s the same approach. It works very well

BeepBoop | 2021-09-12 07:24