13. Столкновение объектов

Занятие 13


Это надо знать

В программе, которую мы написали на прошлом занятии, шарики при столкновении пролетают сквозь друг друг друга. Напишем программу. чтобы шарики при столкновении отталкивались и разлетались в разные стороны.

Рассмотрим случай, когда пересекаются две окружности с центрами в точках (х1, у1) , (х2, у2) и радиусами r1, r2.

Окружности пересекаются, если (x2 - x1)² + (y1 - y2)² < (r1 + r2)²

Найдем расстояние между центрами окружностей. Для этого нам понадобится функция возведения в степень.

Функция pow (a, n) возводит число а в n-ую степень.

distance = pow (x2 - x1, 2) + pow (y1 - y2, 2)

Если   distance < pow (r1 + r2, 2), то  шарики столкнулись.

При столкновении шарики должны оттолкнуться, для этого обменяем скорости  vx и vy мячиков, для этого воспользуемся функцией swap.

Функция swap (a, b) обменивает значения переменных  a и b, т.е в перемененной а будет находиться значение переменной b, а в переменной b - значение переменной а.

Функцию контроля столкновений можно записать следующим образом:

void Collision (Subject* ball1, Subject* ball2)
   {
    double distance = pow (ball1->x - ball2->x, 2) + pow (ball1->y - ball2->y, 2);
    if   (distance < pow (ball1->r + ball2->r, 2))
        {
        std :: swap (ball1->vx, ball2->vx);
        std :: swap (ball1->vy,  ball2->vy);
        }
  }

В функции MoveBalls вызываем функцию Collision для каждой пары шариков (для 4 шариков):

        Collision (&ball1, &ball2);
        Collision (&ball1, &ball3);
        Collision (&ball2, &ball3);
        Collision (&ball2, &ball4);
        Collision (&ball3, &ball4);


Если предположить, что героев можно поместить в круги, то можно рассчитать, когда герои столкнутся, т.е. пересекутся круги, описанные около героев.



Функция Collision проверяет ситуацию столкновения героев Чебурашки (cheb)  и Цыпленка (chik), описанных с помощью структуры Hero.

cheb->x,   cheb->y - координаты центра окружности, описанной около Чебурашки.
chik->x,    chik->y - координаты центра окружности, описанной около Цыпленка.
cheb->r                  -  радиус окружности, описанной около Чебурашки.
chik->r                   -  радиус окружности, описанной около Цыпленка.

void Collision (Hero* cheb, Hero* chik, int* lives)
   {
    distance = pow (cheb->x - chik->x, 2) + pow (cheb->y - chik->y, 2);
    if   distance < pow (cheb->r + chik->r, 2)
        {
        std :: swap (cheb->vx,  chik->vx);
        std :: swap (cheb->vy,  chik->vy);
        }
  }

Рассмотрим случай, когда около героев точнее будет описать прямоугольники.

 

Рассмотрим случаи пересечения прямоугольников:

В условии, которое проверяет  столкновение героев, записываем все возможные варианты:

int chek =   (x1 < x3 && x3 <x2 && y2 < y3 && y3 < y2) ||
                  (x1 < x3 && x3 <x2 && y2 < y4 && y4 < y2) ||
                  (x1 < x4 && x4 <x2 && y2 < y3 && y3 < y2) ||
                  (x1 < x3 && x3 <x2 && y2 < y3 && y3 < y2);

Пример

Движение лягушки и четырех комаров. Комары и лягушка при столкновении "разлетаются".

Посмотреть текст программы

Результат выполнения программы

Домашнее задание


Внести изменения в программу предыдущего домашнего задания: герой должен "реагировать" на столкновение с другими объектами (шариками, другими героями).