Чтобы понять смысл самого процесса, представьте себе, что Вы смотрите сверху на поверхность воды, на которую начинают падать капли дождя. Эти капли создают на воде круги. Я постараюсь объяснить, как создать такой эффект в реальном масштабе времени вне зависимости от фонового изображения или используемой палитры. Yamaha из XYZZ Software создал подобный эффект, но он работает лишь с растрами, использующими линейную палитру. Хотя, если для Вас это не проблема – смотрите его пример. Я хочу поблагодарить Tom Paton за большое количество полезной информации, касающейся исходного кода.
Поскольку мы собираемся создавать волны, давайте поговорим о формулах, которые нам в этом деле помогут. Я бы мог сообщить Вам кое-что о функции Гаусса, но, чтобы не усложнять задачу, я использовал простую комбинацию синуса и косинуса (умноженные на коэффициент зависимости от расстояния до центра).
Вот пример простой синусоидальной волны:
f(alpha) = (sin(alpha) * 90/alpha) * n
где alpha – значение от 0 до 720 градусов, а n - константа (думаю, значение между 3 и 6 должно дать хороший результат). Поиграйте немного с этой формулой. К примеру, пробуйте поделить на alpha в квадрате, или использовать sin(alpha * 2) и sin (alpha/2), чтобы получить вытянутые волны.
Теперь давайте «запустим» волну (увеличим начальный угол и уменьшим амплитуду n). Затем рисуйте концентрические окружности, у которых индекс цвета равен высоте волны на расстоянии r (или, другими словами, вращайте функцию, приведенную выше, относительно начала, с помощью зависимости переменной alpha от уравнения окружности). Вычислите высоту изменений, при помощи определения края волны фильтром в этом буфере:
-1 –1 –1
0 0 0
1 1 1
Матрица фильтра определения края
Сохраняйте возникающие в результате значения в другом буфере (который я назвал градиент). В этот момент Вы должны иметь отдельные кадры с волной в различных стадиях, согласующихся с градиентами. Отобразите изображение на экране, и вычислите смещение по Y у каждого пикселя в «рабочей» области (скажем, 32x32 пикселя), добавляя значение grad[x][y]. И это - все, что потребуется для работы. А выглядит, по моему мнению, просто потрясающе. Скачайте простую демонстрационную программу, которая использует этот эффект (исходник).
Верстка и поддержка Lennart Steinke