Добавить в корзинуПозвонить
Найти в Дзене
Сделай игру

По морям, по волнам: программируем движение корабля

Привет! На связи корабельных дел мастер и мы заставим-таки эти ваши кораблики красиво плавать по волнам. А для этого нам понадобится несложная математическая модель. Волна - это синус. Или косинус - выбирайте, что больше нравится. Кораблик движется вниз и вверх, подчиняясь движению волны. Волна, как будто, движется, но, на самом деле величина просто меняется в зависимости от координат и времени. Пока что волны ещё нет, но колебание кораблика уже можно увидеть. Чтобы легче было разбирать где и что, я добавил центр масс красным перекрестием. Поскольку значение функции синуса находятся в диапазоне от -1 до 1, то умножим выходное значение на некоторую величину - амплитуду - и это значение покажет, как сильно вверх-вниз он может кататься. Кораблик должен плавать, но делать это с уважением, поэтому мы поделим всё пространство на промежутки, скажем, по 40 точек и каждый из этих промежутков будет отслеживать свой кусочек волны. Нам это потребуется чуть позже. А пока - давайте просто добавим в
Оглавление

Привет! На связи корабельных дел мастер и мы заставим-таки эти ваши кораблики красиво плавать по волнам. А для этого нам понадобится несложная математическая модель.

Представим, что наш кораблик выглядит примерно так
Представим, что наш кораблик выглядит примерно так

Модель

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

Пока что волны ещё нет, но колебание кораблика уже можно увидеть.

Пока что это выглядит просто вверх-вниз
Пока что это выглядит просто вверх-вниз

Чтобы легче было разбирать где и что, я добавил центр масс красным перекрестием. Поскольку значение функции синуса находятся в диапазоне от -1 до 1, то умножим выходное значение на некоторую величину - амплитуду - и это значение покажет, как сильно вверх-вниз он может кататься.

Разделение

Кораблик должен плавать, но делать это с уважением, поэтому мы поделим всё пространство на промежутки, скажем, по 40 точек и каждый из этих промежутков будет отслеживать свой кусочек волны. Нам это потребуется чуть позже. А пока - давайте просто добавим волну!

Всё бы хорошо, но качается он мимо волн
Всё бы хорошо, но качается он мимо волн

А качается мимо волн он не случайно: пока что волны и кораблик никак не связаны, то есть величина волны для волны (простите за тавтологию) и вертикальное отклонение кораблика - независимы. Но это мы исправим.

Пока, как видите, код простой и не особо связанный
Пока, как видите, код простой и не особо связанный

Но, чтобы не высчитывать вертикальное отклонение корабля отдельно для волны - мы просто будем передавать в функцию, где отрисовывается волна горизонтальное смещение корабля и будем получать ближайшее значение.

Вот и добавили совпадение
Вот и добавили совпадение

Сделать это было не сложно (хоть и пришлось пойти на некоторое архитектурное преступление).

Теперь вертикальное смещение высчитывается при отрисовке волны
Теперь вертикальное смещение высчитывается при отрисовке волны

В движении

Но это мы делали при условии, что корабль не движется по горизонтали. Теперь пришло время это исправить. Запустим кораблик слева направо, а затем снова и так по кругу. Корабль будет бесконечно двигаться слева направо. И всё это время он должен попадать в волны.

Это не трудно сделать. Каждый кусочек пространства (разделенного вертикальными линиями) разбит на 2n+1 точек (то есть на нечётное количество), что создаёт приемлемую для расчёта частоту дискретизации: волна выглядит не слишком неровной, а смещения плавными.

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

А вот кораблик уже и по волнам плавает
А вот кораблик уже и по волнам плавает

Код, также, немного поменялся.

Хоть поменялся, но не сильно
Хоть поменялся, но не сильно

Корабль плывёт по волнам, признаться, не очень хорошо. Если сильно его замедлить - начнётся "дребезг", но мы это сейчас исправлять не станем. Во-первых, мне просто лень разбираться, во-вторых... во-первых вполне достаточно. Давайте лучше дальше двигаться.

Наклоны

Двигаясь по волнам корабль, что не удивительно, должен наклоняться. Причём наклон может меняться в зависимости от точки на волне. Конечно, можно сделать некоторое усреднение, но мы пойдём по более простому пути - производные. То самое непонятное из школы, что показывает направление движения функции. Непонятно? Неважно, сейчас разберемся.

Производная от синус(х), как всем известно, косинус(х). Ну а если вам это не было известно до сих пор, то теперь уж точно известно. Короче говоря, если значение производной положительное - функция растёт, то есть график движется наверх; если отрицательная - падает, график движется вниз.

Добавили наклон
Добавили наклон

Как это работает: косинус угла - коэффициент; умножая его на предельный угол отклонения (30 градусов) - получается вполне себе достаточное отклонение.

Кажется, цель достигнута
Кажется, цель достигнута

Что ещё можно сделать

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

Кораблик плавает по волнам
Кораблик плавает по волнам

А если тоже хотите поэкспериментировать - то вот вам ссылка. Надеюсь, к тому моменту, когда появится желание её открыть - она будет работать.

P.S. вы, наверное, заметили на изображениях цифры - это peek так работает. Повлиять на это, увы, не могу. Теперь все тайны раскрыты.