Area_entered and area_exited signals overlapping issue

Godot Version

4.2.2

Question

Hi everyone,

i’m new here. I started to play with Godot 3 back in 2020/2021, but now i try to develop at least a few full games. Let’s see how that goes. :smile:

Well, currently for learning purposes i’m building a Columns clone. Not sure if you know what i mean, it’s a falling puzzle piece type game, where you have to match at least three blocks of the same type upon the block landing. I did this with Area2D nodes (the single blocks of the whole 3-block piece), and when a piece lands, the single blocks are “anchored” to the grid.

So far so good. I’m doing a collision check with signals when a new block is on top of an existing one, and setting a variable “contact” to true or false. And you can still move the piece to the left or right for a bit to avoid having it land on top of other blocks, in case there is a gap to have it fall down further. This also works… my problem then comes when i have no gap, so when moving left and right, i constantly get the signals “area_entered”, “area_exited”, and some times they get mixed up (or there really isn’t an order if you have signals sent at the same point in time).

Contact: false
Area Entered!!!
Contact: true
Area Entered!!!
Area left…
Contact: false
Area left…
Area Entered!!!
Contact: true
Area Entered!!!
Area left…
Contact: false
Area left…
Area Entered!!!
Contact: true
Area Entered!!!
Area left…
Contact: false

So as you see in between, when the active piece is still on top of another, there are phases where my variable “contact” is false, because the next “area entered” came before the “area left”. So the block still drops down into another block, at which point it stops, because i can’t move left or right anymore (because the left/right signals kicking in).

I have the feeling i’ve been looking at this for to long now and can’t see the probably easy solution. Or, as this is the first project i want to finish, i’m still missing possible options in my head on how to solve it. :confused:

Does anyone have a smart idea for me how to safely switch the “contact” variable, or maybe another way of detecting or solving this issue?
Currently each block has an area, as well as the puzzle piece itself (which gets deleted upon anchoring the block to the grid). I detect if something is below by the active piece itself sending area_entered and area_exited signals.

Thank you! The game will be put on itch.io when i get it finished, i’m currently working on building kind of a portfolio… :sweat_smile:

I’m not sure I understand your issue. If there are multiple logs from similar pieces using the same script you may be interpreting these logs wrong. You should add unique identifiers to see what’s really happening.

From the logs there seems to be three or more pieces. Also visualize debug collision shapes in the debug menu can help see where the pieces touch and trigger the logs.

1 Like

I’m not sure if i explained poorly, or if an image could help maybe… :sweat_smile:

This is how Columns looks like:
image

Just imagine a collision shape around each block.

So now you shouldn’t be able to drop the next piece any further down because there is no room. For this i have areas (with Collision Shapes) on every block (slightly bigger that a block), and i have an area (with a Collision Shape) on the bottom of my active piece.
Now if the piece is on top of the existing row of blocks and you move left and right (before the active piece has landed and can not be moved anymore), in my first post you see what is happening then. The area on the active piece constantly signals “area entered” and “area exited” for the block you are leaving and the block beside it you are entering. The signal “area entered” is setting a variable “contact” to true, the signal “area exited” is setting the variable to false.
Ideally it should stay true the whole time you move left and right as long as something is beneath (but i need an exit signal, or some other way to check if there is another block below or not).
But as you see in the prints above, sometimes it is false, because the next “area_entered” signal (contact → true) comes before the “area_exited” signal (contact → false). So for a short while i have contact: false, even if there are blocks below.

My interpretation consists of “if area entered set contact = true” and “if area exited set contact = false”. You talk about unique identifiers, i have no clue what that is yet. :neutral_face:

Basically i’m looking for a way to know for sure, when a block is below and when it is not. Currently i’m thinking about maybe the existing blocks somehow signaling contact to the piece (so the opposite of what’s happening now)… so if there is no block below, you don’t get a signal. But i’m working on that, not sure how to implement it yet.

Edit:
Just to clarify, the area_entered and area_exited signals basically happen at the same point in time, because the puzzle piece is moved on a grid (x pixels per movement step), there is no in between cells movement.

In my desperation i found a, kind of, solution… but i guess although it works, it’s not very… best practisy (?) :sweat_smile:

Instead of directly setting and clearing the variable “contact” to true or false, i added another variable for checking, if the area has been entered in the last 0.01 seconds. This works… for now. I still hope someone can enlighten me what would be a better way. Maybe.

func set_contact():
	contact = true
	contact_timeout = false
	await get_tree().create_timer(0.01).timeout
	contact_timeout = true


func unset_contact():
	if contact_timeout:
		contact = false


#  when area is entered
func _on_contact():
	set_contact()


# when area is exited
func _on_contact_loss():
	unset_contact()

So there always has to be a 0.01 second waiting period before the “contact” variable can be set to false again, which fixed it being set to false at the same time when overlapping.

I also saw a Tetris Tutorial on yt, maybe doing the whole thing with tiles/a tilemap would be a better way.

Do these overlap each other?

Like this?

I would probably do a ray cast instead of areas.

If I understand correctly, you should always have one area overlapping your tile after they have all been processed during the physics step, right?

So I guess, in _physics_process(), you could check if moving_area.has_overlapping_areas() is true, and keep moving until it returns false.

Yes, and they have to, because they need to detect blocks around them to determine if they can destroy themselfes at some point (match 3 or more of the same type). Well, in case you meant the blocks, sorry. :slightly_smiling_face:

The area in question is the one on the active block bottom which comes into contact, this one is pretty narrow not to detect neighboring blocks and not more than one area.

Sounds promising, i’ll check that out. Thanks!

Hi again,

i’m experimenting with the has_overlapping_areas() at the moment, and now i noticed, that i can’t use this on the left or right collision shapes, because these are inside separate nodes inside the puzzle piece (because i need to differentiate between bottom, left and right, maybe there is a better way i don’t know about yet).

image

How can i access these areas/collision shapes from my main scene, where i instantiate the puzzle pieces? :confused:

Edit:
After a thinking pause i was able to solve it with putting the two nodes in variables in the puzzle piece, and accessing it from the main scene with
active_puzzle_piece.collision_right.has_overlapping_areas()
Not sure if this is good, but it works for now.
Any thoughts? I always wonder how “veterans” would do it. :slightly_smiling_face:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.