pythonpygameterrain

How to avoid collision on random placement?


I'm trying to scatter 100 rocks over a series of coordinates randomly. Sometimes rocks overlap. If they do, I want to create new coordinates until it doesn't collide anymore. How to do this?

I've tried detecting collisions, but it always returns True. __init__ generates coordinates with random.randint(-2500,2500). When the rocks are created in the for loop, each rock is added to the list. In the update function it checks for rectangular collisions. How can I fix this?


Solution

  • Well, I guess there are a few ways you can approach this problem:

    1) The first would be the one you already used, you would check for collisions each time you generate a rock and if a collision exist you would regenerate a position for the given rock

    2) The second one would be to slice your "field" into rectangles of the size of the rock, just like a tilemap, therefore creating a list of possible positions, something like this:

    possible_positions = [(i, j) for i in range(x_size_field//x_size_rock) for j in range(y_size_field//y_size_rock)]
    for i in range(n_of_rocks):
        rock_pos = random.choice(possible_positions)
        possible_positions.remove(rock_pos)
    

    But this approach would implicate in a given set of possible positions that make a "uniform" rock distribution

    3) So if its really necessary to make put the rocks on absolute random positions you could create a list of possible positions like the following:

    possible_positions = [[(i, j) for j in range(y_size_field-y_size_rock)] for i in range(x_size_field-x_size_rock)]
    for i in range(n_of_rocks):
        # X and Y represente positions on the list not on the field
        x = random.randint(0, len(possible_positions))
        y = random.randint(0, len(possible_positions[x]))
    
        # The rock positions
        rock_pos = possible_positions[x][y]
    
        # Now we remove the positions on the region of the new rock
        for i in range(x,x+x_size_rock):
            possible_positions[i] = possible_positions[i][0:y] + possible_positions[i][y+y_size_rock:-1]
    
        if [] in possible_positions:
            possible_positions.remove([])
    

    Of course this code may generate errors (its a rather simple code) and it needs some optimizations, but i think you may get the general ideia from this.

    Sorry about my english