Attempting to prevent overlap

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

I am randomly placing nodes onto a target, and want to randomise the positions to the point where there is zero overlap. This happens at the start of the game.

I realised you cant do an overlaps test in the same frame you move things around, so I am trying to yield to the next frame. The issue is, my overlap_count is printing out zero, but I am getting overlaps. My collision shapes are correct, and I am setting the collision masks on the Area2D nodes correctly I think.

func randomise_card_positions():
	var rng = RandomNumberGenerator.new()
	
	rng.randomize()
	
	var cards = get_tree().get_nodes_in_group("playing_cards")
	
	var t_size = target.get_node("Sprite").texture.get_size()[0]	
	t_size = 800  # TODO manual override
	for card in cards:
		
		var random_x = rng.randi_range(-t_size/2.0,t_size/2.0)
		var random_y = rng.randi_range(-t_size/2.0,t_size/2.0)
		var random_angle = rng.randi_range(0,359)
		
		card.rotation_degrees = random_angle
		card.position = Vector2(random_x, random_y)
		
	
	
		
		
func remove_overlaps():
	var cards = get_tree().get_nodes_in_group("playing_cards")
	print("Number of cards: " + str(len(cards)))
	var overlap_count = 100
	
	while overlap_count > 0:
		overlap_count = 0
		var overlapping_areas
		for card in cards:
			overlapping_areas = card.get_overlapping_areas()
			
			if overlapping_areas.empty() == false:
				overlap_count += 1
				
		print("Number of overlapping areas: " + str(overlap_count))
		
		if overlap_count > 0:			
			randomise_card_positions()
			yield(get_tree(), "idle_frame") 
			

Output when this completes:

enter image description here

Output in the console:

Number of overlapping areas: 16
Number of overlapping areas: 15
Number of overlapping areas: 12
Number of overlapping areas: 3
Number of overlapping areas: 0

Note: I have also tried yielding to the “physics_frame” but this doesnt work either, the only way I can get it to work is by yielding to a timer of 0.1 seconds, and randomising one overlapping card at a time rather than all of them.

:bust_in_silhouette: Reply From: klaas

Hi,
i think t has something to do with this

Docs say:
Note: The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.

So either you have to wait till the next physics frame or you use another mehtod. Since i dont see a way to force a physics update in 2D.

A more solid approach would be to use poisson disc sampling.

this project may help you with this…

Hi,

This seems to work.

yield(get_tree().create_timer(0.1), “timeout”)

And if I randomise just the overlapping card, not all of them, I do get a reasonable outcome. I thought I was waiting for the next physics frame. I tried yielding to the pyhsics frame instead, but that didn’t work. I like that link (thanks), but I dont want an even distribution. I am trying to attach random playing cards to a spinning target.

indy2005 | 2020-09-14 21:39