§ Демонстрация
Переписал программу на javascript, чтобы показать, как выглядит эффект воды "вживую".Demo: Анимация мелкой воды
§ Код
#include <qblib.c> #define PALETTENUM 5 // Исходная палитра static const unsigned char pal[PALETTENUM][4] = { {1, 0, 0, 32}, {64, 0, 0, 64}, {128, 0, 0, 128}, {192, 0, 192, 192}, {255, 255, 255, 255}, }; float Fp[ 320 ][ 200 ]; // Новое поле float Fn[ 320 ][ 200 ]; // Предыдущее поле void init() { srand(3); for (int i = 0; i < 200; i++) for (int j = 0; j < 320; j++) Fp[j][i] = 0; generate_palette(PALETTENUM, pal); } float xy(int x, int y) { if (x < 0) x = -x; if (y < 0) y = -y; if (x >= 320) x = 639 - x; if (y >= 200) y = 399 - y; return Fn[x][y]; } // Генератор волн void waves() { int i, j; // Генераторы if (mouse.st & LF_CLICK) Fn[ mouse.x ][ mouse.y ] = (rand()%256) - 16; // Случайные капли for (j = 0; j < 4; j++) Fn[ rand() % 320 ][ rand() % 200 ] = (rand() % 32); // Релаксация, выше 1.0f не делать float omega = 0.99; float laplas; // Основная функция for (i = 0; i < 200; i++) { for (j = 0; j < 320; j++) { // Расчет лапласиана laplas = xy(j-1, i+0); laplas += xy(j+1, i+0); laplas += xy(j+0, i-1); laplas += xy(j+0, i+1); // Дополнительная точность laplas += xy(j-1, i-1); laplas += xy(j+1, i+1); laplas += xy(j-1, i+1); laplas += xy(j+1, i-1); laplas = (laplas / 8.0f); // Итоговое значение Fp[j][i] = laplas + omega*(Fn[j][i] - Fp[j][i]); // Релаксация, чтобы волны успокаивались Fp[j][i] *= 0.999f; } } // Обмен полей for (i = 0; i < 200; i++) for (j = 0; j < 320; j++) { float sw = Fp[j][i]; Fp[j][i] = Fn[j][i]; Fn[j][i] = sw; } } // Перерисовать void redraw() { for (int y = 0; y < 200; y++) { for (int x = 0; x < 320; x++) { int a = 128 + 12*(Fn[x][y]); a = a < 1 ? 1 : (a > 255 ? 255 : a); pset(x, y, a); } } } int main(int argc, char* argv[]) { screen(13); init(); while (sdlevent(EVT_REDRAW)) { waves(); redraw(); } return 0; }