Вариант 1:
Нужно, чтобы каждая окружность сама проверяла своё состояние и сообщала слушателю.
Как только создаётся окружность - вешаете на неё обработчик события столкновения.
Вариант 2:
Следите за центрами всех окружностей, чтобы контролировать столкновение.
Столкновение (касание): когда расстояние между двумя центрами окружностей равно сумме радиусов окружностей вокруг этих центров. И, соответственно, проверка на пересечение: расстояние - меньше или равно.
Проверка - итеративная:
1. После первой проверки - сортируем все пары центров с зазорами между кругами от самого близкого к самому дальнему.
2. При второй - проверяем, начиная с самого близкого и сразу рассчитываем скорость и вектор смещения. Теперь, добавляем скорость: сортируем от максимальной скорости с минимальным зазором к минимальной скорости с максимальным зазором.
3. При последующих используем информацию предыдущего шага для определения порога зоны "отсечения хвоста" при проверке по отсортированному списку: threshold.
Т.е., если мы видим, что ускорение или линейная скорость за заданное время не позволят им пересечься на этом фрейме, то мы их просто не проверяем и ставим метку: через сколько итераций мы будем проверять каждую из них (резервируем их для исключения на нескольких последующих итерационных проверках).
Таким образом, мы экономим "пустые" циклы при просчёте столкновений.