Обнаружение столкновения между многими объектами черепахи в python - PullRequest
0 голосов
/ 25 марта 2020

Я медицинский редактор для Википедии (с почти нулевым python опытом), и мы пытаемся создать симуляцию эффектов социального дистанцирования. Я пытаюсь заставить группу кругов подпрыгивать в квадратном пространстве. У меня они отскакивают от стен, но я не уверен, как обнаружить столкновение между шарами. Я создал определение is_collided_with, но строка

if is_collided_with(ball, ball):
            ball.dy *=-1
            ball.dx *=-1

замораживает все. Если вы удалите его, вы увидите движение (скорость может отличаться от того, что я понимаю). Конечная цель состоит в том, чтобы изменить цвет от здоровья к инфекционному, вылечить и показать, как социальное дистанцирование работает с различным числом людей, следующих за ним.

1 Ответ

1 голос
/ 25 марта 2020

Проблема в этой строке:

if is_collided_with(ball, ball):

Вы дважды передаете один и тот же объект ball, обрабатывая его так, как если бы он разделял шары. В основном, для каждого шара в вашем списке шаров, оператор if говорит: "Этот шар сталкивается сам с собой?" - что всегда будет верно для каждого кадра симуляции. Поэтому вы всегда вводите тело оператора if и переворачиваете текущие векторы x- и y-шаров, что приводит к тому, что каждый шар просто колеблется на месте.

Наивное решение включает сравнение текущий шар со всеми другими шарами в симуляции. Я говорю «наивный», потому что, хотя это работает, оно становится ужасно неэффективным и медленным для большего количества шаров. Более сложное решение будет использовать некоторую технику разделения пространства, такую ​​как квадродерево, чтобы значительно улучшить производительность (это работает только путем сравнения шаров, которые могут быть близко друг к другу, тогда как все другие шары, которые находятся далеко, отбраковываются и не рассматриваются для сравнение).

В вашем случае, пока количество шариков невелико, наивное решение должно работать нормально. Это выглядело бы примерно так (обратите внимание на вложенную форму -l oop):

while True:
    wn.update()
    for ball in balls:
        ball.sety(ball.ycor() + ball.dy)
        ball.setx(ball.xcor() + ball.dx)
        for other_ball in balls:
            if other_ball is ball:
                # We are not interested in balls colliding with themselves.
                # Skip the current iteration of the inner for-loop, and move on to the next ball
                continue
            if is_collided_with(ball, other_ball):
                ball.dx *= -1
                ball.dy *= -1

        if ball.ycor() <-300:
            ball.dy *=-1
        if ball.ycor() >+300:
            ball.dy *=-1
        if ball.xcor() >+300:
            ball.dx *=-1
        if ball.xcor() <-300:
            ball.dx *=-1

И еще одна вещь, имейте в виду, что технически то, что два шарика сталкиваются, не означает, что их направление - компоненты вектора (и x и y) должны быть / должны быть перевернуты. Представьте себе сценарий, в котором два шара движутся в одном и том же направлении, но с немного отличающимися скоростями, где мяч впереди медленнее, чем тот, который позади него (который догоняет) - если они столкнутся, было бы неправильно перевернуть оба направления. -векторные компоненты.

...