SFML и C++ Уроки \ Разработка игр › Форумы › Логика игр › Как реализовать коллизию между двумя окружностями?
Помечено: Окружность
В этой теме 2 ответа, 2 участника, последнее обновление KindRedSand 5 года/лет, 7 мес. назад.
-
АвторСообщения
-
Нужно что бы при соприкосновений две окружности не входили друг в друга, а стояли впритык.
Как это реализовать?
Помоему в разы проще чем делать коллизию на SAT. Берёшь вектора цетров окружностей и проверяешь дистанцию между ними – если дистанция меньше чем сумма радиусов – выталкивай вектора центров в противоположных направлениях на велечину пересечения.
Будет примерно такC++1234567891011121314151617181920212223242526272829303132333435363738394041424344454647struct Circle{float r = 10;sf::Vector2f center = sf::Vector2f(0,0);}//Угол между двумя векторами//Возвращает градусы!float getAngle(sf::Vector2f start, sf::Vector2f end){return atan2((start - end).y, (start - end).x) * 180 / 3.14159265;}//Длинна вектораfloat getVDistance(sf::Vector2f start, sf::Vector2f end){return std::sqrt((abs((start - end).x)*abs((start - end).x)) + (abs((start - end).y)*abs((start - end).y)));}//Поворот вектораsf::Vector2f vectorRotate(sf::Vector2f& vec, const double deg){double theta = deg * mRad;auto cs = cos(theta);auto sn = sin(theta);sf::Vector2f p = vec;return vec = Vector2f(cs * p.x - sn * p.y, sn * p.x + cs * p.y);}void foo(Circle fi, Circle se){float dist = getVDistance(fi.center, se.center);if ( dist < (fi.r + se.r)){float angle = getAngle(fi.center, se.center);float delta = (fi.r + se.r) + dist;delta /= 2;sf::Vector2f vec = vectorRotate(sf::Vector2f(1, 0), angle)vec.x *= delta;vec.y *= delta;fi.center += vec;vec = vectorRotate(sf::Vector2f(1, 0),360 - angle)vec.x *= delta;vec.y *= delta;se.center += vec;}//Код набросан на вскидку ибо давно уже (больше 2 лет ибо мне хватает SAT) не задумывался о движке коллизии.}Поправочка. в строке vec = vectorRotate(sf::Vector2f(1,0),360 angle) должно быть не 360 а 180. Ночью котелок порой варит вообще не в ту сторону
-
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.