How can i spawn random car item in many position without car items overlapping each other.

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

what i did was, i use staticbody2D to wrap my car item.
secondly i instance the car item in my main scene and finally i use position2D
to duplicate the car in different positions since the position will be generated randomly.

#The Problem is the positions of my random car keep overlapping, meaning some are created on top of each other.

#code for my staticbody2D car item

extends StaticBody2D

const car_list = [“car1”,“car2”,“car3”,“car4”,“car5”,“car7”,“car8”]
var pos_x=200
var pos_y=200

func _ready():
randomize()
var current_car = car_list[randi() % car_list.size()]
get_node(“carD”).animation = current_car
pos_x=rand_range(600,1650)
pos_y=rand_range(-600,-390)
position.x = pos_x
position.y = pos_y

#what i want is the random position should not duplicate or over lap

Instead of the car item setting its own position, you could move that code to whatever instances the car item. That way you could compare the random position to see if it’s too close to another car item.

bepis | 2021-12-07 00:51

thanks man, But by what means do i give a minimum
distance to each random car. A code illustration will
be appreciated.

gieyan | 2021-12-07 09:27

I’m not sure how you create the Car items now but if it’s by GDScript, I would just position the items there.

# car item spawner
func spawn_car_items():
    var car_items = []
    # create 25 car items
    for i in range(25):
        var x = 0
        var y = 0
        var too_close = true
        while(too_close):
            x = randrange(600,1650)
            y = randrange(-600,-390)
            too_close = false
            for item in car_items:
                var other_pos = item.get_pos()
                var x_diff = abs(x - other_pos.x)
                var y_diff = abs(y - other_pos.y)
                if x_diff < 32 && y_diff < 32:
                    too_close = true
                    break
    var instance = CarItem.instance()
    instance.set_pos(Vector2(x, y))
    car_items.push_back(instance)

# car item
const carlist = ["car1","car2","car3","car4","car5","car7","car8"]

func ready():
    # ideally you just call randomize once in your game at the start
    # randomize()
    var currentcar = carlist[randi() % carlist.size()]
    getnode("carD").animation = currentcar

This code’s not great but if you aren’t running it too often, it should be okay. Another, probably easier, solution is to attach an Area2D and use its get_overlapping_areas method.

bepis | 2021-12-07 16:20

:bust_in_silhouette: Reply From: Inces

Interesting approach. Since You already used another node to populate screen with cars, You can use this node again. Use Area2d instead of Position2D, and make use of Areas collision detection. Give it collision shape resembling capacity of your car, before placing car check if it would collide, if not - place the car, if yes - go to next iteration.

There is also other option - You can make cars detect surroundings on ready(), and when they would find another car within some rect of global_positions -they would queue itself free