Hi,

I'm writing a 2D platformer, with a player sprite and a fire sprite.

The player can walk through the fire sprite unimpeded, but will take damage - whats the best way to detect a collision like this.

I've tried:

  • Kinematic2D + CollisionShape2D - I can detect the collision with this, but the Fire sprite is solid to the player.

  • Area2D + CollisionShape2D - This works well and the player can pass through the fire, but I can only detect the event when the player enters or leaves the fire.

Is there a method that will continuously call an event whilst the two sprites intersect?

Or is the 'proper' way to do this to assume that once the enter event is called, the sprites are touching until the exit event called?

Thanks.

You can also use the 2d version of rigid-body. Make its collision layer zero, but its mask to detect the fire sprite or any AOE enemy -only-. Then make the rigid body follow your kinematic with a joint or use _integrate_forces()

Turn on collision monitoring and increase the contact count high enough for your needs (like 1 or 2 or higher).

Then in _physics_process, you can get the contacts and check if fire sprite is one of them.

Or use 'AOE' specific areas on both your player and the enemy and setup detection to only pick up between the two of areas.

Collision layers and masks are your friend here.

OK, thanks for your response.

Contact Monitoring sounds like what I'm looking for.

So am I correct in assuming the difference between Area2D and RigidBody2D when it comes to contacts is:

Area2D - emits a signal when an another sprite enters or leaves the area, but doesn't continuously the contact between the two whereas RigidBody2D - Can continuously report the contact

so if my character stands in the fire a RigidBody2D will keep reporting he is in there and he'll keep taking damage?

Cheers.

Area2D nodes can tell you if a physics node (or other Area2D) is within the boundaries. You can use the body_entered and body_exited signals to detect right when something hits the Area2D. You can use the get_overlapping_bodies and get_overlapping_areas functions to tell if something is still inside the Area2D. One downside of Area2D nodes: It does not return collision normal or position data, it just tells you if a node is inside or outside.

A RigidBody2D will report contacts when it resolves a collision. The collision data returned by the contact data are where the RigidBody2D overlaps when it tries to find a physics state where neither body is overlapping, if that makes sense. This returns the position point(s) and their normals, but once the bodies are not overlapping it will not return any contact data. If you set the layer to 0 but leave the masks like normal, then it will resolve collisions but the rest of the physics world will be unable to see or interact with it. If you are constantly pushing/updating the RigidBody2D so its at the same position as the character, then you should continually get collision data from the contact monitor as it tries to resolve the collisions.

For the fire sprite, I might recommend using an Area2D attached to the fire if you are only wanting to know if a KinematicBody2D is inside the fire or not. This should be a tad easier for performance since its not trying to resolve collisions. Additionally, level geometry shouldn’t return false positives or anything like that when using an Area2D. (Not to say the RigidBody2D idea is bad: Its actually pretty clever! I just see some downsides that may be undesired)

For a fire to damage the player, you could try something like this using an Area2D:

extend Area2D
const FIRE_DAMAGE = 10
func _physics_process(delta):
	for body in get_overlapping_bodies():
		if body.has_method(“take_damage”):
			body.take_damage(FIRE_DAMAGE * delta)

Perfect, that was exactly what I was looking for - thanks for your help!

2 years later