@Span4ev

Как рандомно расположить объекты без пересечений?

Я работаю в игровом движке Renpy, но можно представить Pygame. Да, мне подсказали, что в Pygame есть встроенные методы collide, но в Renpy их нет. Поэтому я пытаюсь написать алгоритм.
Я хочу расположить какие-то объекты (кнопки, изображения, прямоугольники) в случайных координатах с помощью функции random. У объектов есть ширина и высота, это не просто точки.
Но так как random непредсказуема, то очень часто при расположении объектов, они частично или полностью закрывают друг друга, то есть

ширина изображения = 100 пикселей
высота изображения = 100 пикселей

1 объект:
случайно полученная икс координата = 0
случайно полученная игрек координата = 0
объект занимает координаты от 0 до 100 по x и от 0 до 100 y

2 объект:
случайно полученная икс координата = 22
случайно полученная игрек координата = 33
объект занимает от 22 до 122 по x и от 33 до 133 по y

В итоге объект 2 заходит в границы объекта 1 и частично его закрывает. Это пример.

Нужно чтобы каждый новый созданный объект на залезал на границы уже имеющихся, то есть в описанном выше примере объект 2 получает координаты 22 и 33 для икс и игрек соответственно, то к этим числам прибавлялось смещение, как минимум на ширину и высоту объекта.

Допустим:
первая итерация цикла и полученные случайные координаты: x=0, y=0
Добавление кортежа в список координат

вторая итерация цикла: x=22, y=33

Проверка списка - ага, там уже есть числа от x 0-100 и y 0-100.
Значит:
# x=22
# y=33
x += 100 # ширина объекта
y += 100 # высота объекта.
x = 122 # новая координата
y = 133 # новая координата

Объекты не пересекаются. На словах легко, а на практике... Как-то это делается в тысячах играх, когда объекты располагаются в случайных местах, но не мешают друг другу. Уверен, это должно быть просто. Но у меня плохо с математикой, да и с питоном, так что вся надежда на вас.

Я давно ещё пробовал сделать это в Pygame, но ничего не вышло и я опустил руки и потому забросил пайгейм, разочаровавшись в себе. Теперь снова вспомнил про это, но так и не осенило. Я привёл пример, до которого додумался, но он не рабочий.

width     = 50
height    = 50
start_x   = 0
start_y   = 0
end_x     = screen_width   - width
end_y     = screen_height  - height
coors     = []

count     = 20

    for i in range(count):
        rand_x = random.randint(start_x, end_x)
        rand_y = random.randint(start_y, end_y)
        temp  = (rand_x, rand_y)
        
        if not coors:
            coors.append(temp)
        else:
            for k in coors:

                temp_x = k[0] + width  
                temp_y = k[1] + height 

                if rand_x >= k[0] and rand_x <= temp_x:
                    rand_x += width + margin
                else:
                    rand_x = rand_x

                if rand_y >= k[1] and rand_y <= temp_y:
                    rand_y += height + margin
                else:
                    rand_y = rand_y

                temp  = (rand_x, rand_y)
            coors.append(temp)
  • Вопрос задан
  • 489 просмотров
Пригласить эксперта
Ответы на вопрос 2
phaggi
@phaggi Куратор тега Python
лужу, паяю, ЭВМы починяю
Для решения этой проблемы в игровых движках обычно есть встроенный механизм collide или что-нибудь в таком духе.
Например, в pygame можно создать объект типа Rect и у него будет методы colliderect(Rect) и collidelist(list); первый проверяет пересечение текущего и указанного объектов Rect; последний метод берет список объектов типа Rect, поданный на вход, и проверяет на пересечение с хотя бы одним из них.
Так что всё, что вы хотите сделать, уже есть в pygame «из коробки»
Вам лишь необходимо почитать документацию.
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
В промышленности есть задача под названием "Оптимальный раскрой". Не знаю как это делать в Pygame, но это обобщенная постановка для фигур произвольной формы на плоскости. Например - заготовок изделий на листе металла.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы