extends Node2D
const RANGE = 1200
const SPEED: int = 300
var travelled_distance = 0
var health = 100
var explosion_damage: int = 3
var explosion_radius: float = 100
func _physics_process(delta: float) -> void:
position += transform.x * SPEED * delta
###queue_free()
func _on_area_2d_body_entered(body: Node2D) -> void:
if body.is_in_group("enemies"):
explode()
func explode():
var explosion_area = Area2D.new()
var collision_shape = CollisionShape2D.new()
collision_shape.shape = CircleShape2D.new()
collision_shape.shape.radius = explosion_radius
add_child(explosion_area)
explosion_area.add_child(collision_shape)
for body in explosion_area.get_overlapping_bodies():
if body.has_method("take_damage"):
body.take_damage(explosion_damage)
Question
I am trying to make my bullets change into explosions on impact, I get no errors yet its still not working, for some reason the explode() function doesn’t even get activated because no Area2D has been created after touching the enemy
I mean does your bullet mesh have a collisionshape associated with it and have you checked to see if it works e.g. when bullet hits enemy, print something?
Is your enemy a CharacterBody2D? Because the body_entered signal works only on the inherited classes from PhysicsBody2D, which is CharacterBody2D, RigidBody2D or StaticBody2D.
Did you connect the body_entered signal of the Area2D in the inspector? Your method should have this green arrow symbol next to it.
The monitoring of the Area2D should be turned on
The collision_mask of your Area2D should be the same as collision_layer of your enemy
Thanks, the body entered signal wasn’t connected, now it prints ok. Also I just found out that I had a spelling problem with my groups so thats why the explode func wouldn’t work…
the explosion still doesn’t do any damage
for body in explosion_area.get_overlapping_bodies():
if body.has_method("take_damage"):
body.take_damage(explosion_damage)
my enemy has the take damage func so it should work
Show your enemy class script please.
What happens if you add these 2 print statements? Which of these get printed (if any)?
for body in explosion_area.get_overlapping_bodies():
print("should be damaged")
if body.has_method("take_damage"):
print("has take_damage method")
body.take_damage(explosion_damage)
extends CharacterBody2D
var health = 3
@onready var player = get_node("/root/game/player")
func _physics_process(delta: float) -> void:
var direction = global_position.direction_to(player.global_position)
velocity = direction * 200
move_and_slide()
func take_damage():
health -= 1
if health == 0 :
queue_free()
for some reason I get an error and no prints when the bullets touch the enemy
E 0:00:02:0766 bomb.gd:30 @ explode(): Can’t change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.
<C++ Error> Condition “area->get_space() && flushing_queries” is true.
<C++ Source> servers/physics_2d/godot_physics_server_2d.cpp:355 @ area_set_shape_disabled()
bomb.gd:30 @ explode()
bomb.gd:20 @ _on_area_2d_body_entered()
oh damn thats what I get for copying code from my other games, thanks, I still have some issues but I think I can figure it out and post the solution, if not I will ask soon
because I got the “Can’t change this state while flushing queries. Use call_deferred()”
I added call_deferred() here
func explode():
var explosion_area = Area2D.new()
var collision_shape = CollisionShape2D.new()
collision_shape.shape = CircleShape2D.new()
collision_shape.shape.radius = explosion_radius
add_child(explosion_area)
explosion_area.call_deferred("add_child", collision_shape)
now the game straight up crashes and just says breakpoint
the breakpoint happens here in the first line
for body in explosion_area.get_overlapping_bodies():
print("should take damage")
if body.has_method("take_damage"):
print("dmg")
body.take_damage(explosion_damage)