Разновидностей алгоритмов генерации "плазм" столько же, сколько, наверное, звезд на небе. Но связывает их вместе принцип плавного формирования перехода цветов. Для бесшовного формирования цвета очень часто используются тригонометрические функции. Во-первых, потому что они периодические, т.е. через определенный промежуток значения функции повторяются, а во-вторых, они возвращают непрерывные значения, т.е. бесконечно малому приращению аргумента соответствует бесконечно малое приращение функции. Благодаря этому можно используя простые комбинации функций получать плавное возрастание и убывание цветов. Я попробую рассмотреть один из вариантов, который использует функции синуса и косинуса. Сначала произведем небольшую оптимизацию. Вычисления тригонометрических функций довольно накладное для процессора занятие. А поскольку таких вычислений на каждом кадре анимации придется делать по нескольку штук, то желательно нужные нам значения рассчитать заранее. Еще раз напомню, что функции синуса и косинуса – периодические. Их наименьший интервал, через который они начинают повторять значения, это 360 градусов или 2 * Пи. Поэтому, чтобы запомнить только уникальные значения (все остальные можно вычислить на их основе) достаточно рассчитать кусочек от 0 до 2 * Пи. Сделаем по 255 значений для каждой из функций. Для этого создадим два списка по 255 значений в каждом. Для того чтобы значения синуса и косинуса были в диапазоне от 0 до 1, разделим наш счетчик index на 255. А чтобы внутри массива получился только один период значений функций - умножим аргумент еще на 2 * Пи. Теперь внутри массивов мы имеем кусочки синусоиды и косинусоиды по одному полному колебанию. Подобный подход к работе с тригонометрическими функциями, очень часто используется при программировании демо-работ, для оптимизации скорости выполнения программ. Дополнительно сделаем обратную процедуру, напишем функцию, которая по значению на вход, будет возвращать индекс из нашего массива, который бы соответствовал входному значению, но после получения остатка от деления на длину нашего массива. Звучит очень сложно, но попробую объяснить на пальцах, ну или на картинках: Пусть у нас есть массив из трех элементов: Есть число 5, которое мы хотим применить к нашему массиву и понять как бы оно расположилось на нашем массиве, если взять от него остаток от деления по длине нашего массива. Число 5 можно представить, как еще один массив: Уберем из нашего второго массива длину первого: Остается два элемента: И пытаемся их совместить с нашим первоначальном массивом: Таким образом наше число 5, попадает на ячейку с номером 2. Вот кратко суть функции по высчитыванию индекса в массиве. В нашем случае будем вычислять индекс для диапазона от 0 до 2 * Пи. Функция вернет целое значение в диапазоне от 0 до 255, получая на вход какое-то число и подставляя его в диапазон от 0 до 2 * Пи, который разбит на 255 частей. А вот дальше уже пойдет почти "магия", поскольку мы начнем получать цветовые характеристики точек по формулам с использованием тригонометрических функций. Почему "магия"? Потому, что объяснить некоторые вещи не до конца получается, во всяком случае у меня. Просто при каких-то сочетаниях функций и арифметических действий - результат будет довольно красивым. И здесь зачастую приходится действовать эмпирическим путем. Но обо всем по порядку. Плазма не должна быть статичной! Чтобы этого добиться, нужно на каждой итерации обновления экрана и генерации кадра изображения, добавлять какую-то динамическую составляющую в расчет картинки. Создадим переменную t (по умолчанию равная 0),  в которой будет накапливаться сдвиг для генерации изображения. Пусть эта переменная, на каждом кадре изменяется на значение delta: И как только переменная t превысит значение 2 * Пи, то будем сбрасывать ее в 0. Т.е. она по кругу будет проходить через 255 значений, пока не доберется до 2 * Пи. Приступаем к генерации изображения, сначала размещу часть кода, затем поясню: Итоговая анимация плазмы будет вот такая: У нас есть два вложенных цикла. Первый проходит по строкам изображения, второй по колонкам. Пересечение этих циклов - это обрабатываемая точка на экране с координатой i,j. Формируем для каждой из этих координат, ее аналог, но выравненный по диапазону от 0 до 1. Делается это просто делением на ширину первоначального диапазона, для y, это i / MY, для x, это j / MX. Теперь добавим "хаоса" в генерацию изображения. Сделаем три коэффициента для трех составляющих цвета: a1 для красного (red), a2 для зеленого (green), a3 для синего (blue). Вычисляем их по следующему принципу: получаем значение индекса для координаты x + t и получаем значение синуса или косинуса для этого индекса. Полученное значение умножаем на произвольный коэффициент. На самом деле это число поможет нам изменять количество волн на экране. Например: Как видите, здесь можно играть коэффициентами как угодно, результат аналитически просчитать заранее сложно. Но это мы пока вычисляли коэффициенты, теперь используем их при вычислении цветов r, g, b. Мы опять применим сочетания синусов и косинусов взятые из таблиц, но с учетом добавления туда коэффициентов a. Что именно использовать cos или sin не сильно принципиально, просто их смещение в разных сочетаниях дает интересные результаты. Умножение на 100 здесь служит для того, чтобы дробное значение цвета привести к диапазону от 0 до 255, в котором его обрабатывает библиотека PyGame. Советую "поиграться"  коэффициентами, расположением функций sin и cos. Получаются очень примечательные картины. Итоговый код:  Ссылка на предыдущую статью: Разбираем алгоритмы компьютерной графики. Часть 5 – Анимация «Shade Bobs» В следующий раз рассмотрим алгоритм искажений на плоскости, например эффект линзы.