Реализация отскока круга от растра

220
13 мая 2021, 08:40

Третий день пытаюсь реализовать реалистичный отскок, вроде того, который был у гранаты в Worms 2D. Перепробовал несколько алгоритмов, но все они работают плохо.

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

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

Попытался определять, какие непроходимые пиксели попадают внутрь оболочки гранаты в потенциальной позиции. Затем я строю вектор для каждого такого пикселя - от пикселя к центру гранаты. Все вектора всех пикселей складываются, а потом нормализуются. Я надеялся, что это позволит мне получить вектор взаимодействия с землей в точке касания (нормаль).

Это тоже почему-то не работает. Объект лишь иногда отскакивает нормально.

Я бы хотел узнать вот что:

  1. Как рассчитать результирующий вектор скорости после абсолютно упругого столкновения?

Пытаюсь делать так:

velocity_x -= 2 * velocity_x * normal_x;
velocity_y -= 2 * velocity_y * normal_y;
  1. Есть ли какие-нибудь алгоритмы, чтобы движущийся объект (имеющий радиус) достаточно правдоподобно отскакивал от границы растра?

Вот тестовый код, если кому-то интересно:

void Grenade::processing(float _dt, Image &ground)
{
    velocity_y += GRAVITY * _dt;
    auto checkArea = [](const size_t _x, const size_t _y)->bool
    {
        if ((_x >= 0U) && (_x < WINDOW_WIDTH) && (_y >= 0U) && (_y < WINDOW_HEIGHT))
        {
            return true;
        }
        else {
            return false;
        }
    };
    auto checkCollision = [&ground, &checkArea](const size_t _x, const size_t _y)->bool
    {
        if (checkArea(_x, _y) == true)
        {
            auto pixel = ground.getPixel(_x, _y);
            if (pixel.a != 0)
            {
                return true;
            }
        }
        return false;
    };
    const float new_x = x + velocity_x * _dt;
    const float new_y = y + velocity_y * _dt;
    float force_x = 0.f;
    float force_y = 0.f;
    for (int ix = new_x - GRENADE_RADIUS; ix < new_x + GRENADE_RADIUS; ++ix)
    {
        for (int iy = new_y - GRENADE_RADIUS; iy < new_y + GRENADE_RADIUS; ++iy)
        {
            if (checkCollision(ix, iy) == true)
            {
                const float fx = ix - new_x;
                const float fy = iy - new_y;
                const float fr = sqrt(pow(fx, 2) + pow(fy, 2));
                if (fr <= GRENADE_RADIUS)
                {
                    force_x += fx / fr;
                    force_y += fy / fr;
                }
            }
        }
    }
    if ((force_x != 0.f) || (force_y != 0.f))
    {
        const float force_r = sqrt(pow(force_x, 2) + pow(force_y, 2));
        force_x /= force_r;
        force_y /= force_r;
        velocity_x -= 2 * velocity_x * force_x * ELASTICITY;
        velocity_y -= 2 * velocity_y * force_y * ELASTICITY;
    }
    else {
        x = new_x;
        y = new_y;
    }
}
Answer 1

Мне удалось выяснить, что отскок происходил неправильно из-за того, что я рассчитывал новую скорость по неправильной формуле.

Правильная:

velocity_x = velocity_x - 2 * force_x * (force_x * velocity_x + force_y * velocity_y);
velocity_y = velocity_y - 2 * force_y * (force_y * velocity_y + force_x * velocity_x);
READ ALSO
Абстрактный класс

Абстрактный класс

У меня есть некий абстрактный класс, назовем его Abs:

129
Nemiver: при отладке rand() вылезает ошибка

Nemiver: при отладке rand() вылезает ошибка

При отладке функции rand() вылезает ошибка: Не удалось найти файл /build/glibc-LK5gWL/glibc-223/stdlib/random

99
Верстка Flex элементов при скролле по оси X

Верстка Flex элементов при скролле по оси X

Есть вот такой кодПри уменьшении ширины добавил скролл по оси x но элементы текст перепрыгивает на вторую строчку

156
Делаю django ЧПУ с помощью slug но выдает ошибку

Делаю django ЧПУ с помощью slug но выдает ошибку

Я хочу чтобы url выводилося названия статьи типо programs/kak-vzlomat-jopu или как то такИ еще настораживает то что как рагумент берет slug : 13 а это вообще...

160