§ Демонстрация
Переписал программу на javascript, чтобы показать, как выглядит эффект воды "вживую".Demo: Анимация мелкой воды
§ Код
1#include <qblib.c> 2 3#define PALETTENUM 5 4 5// Исходная палитра 6static const unsigned char pal[PALETTENUM][4] = 7{ 8 {1, 0, 0, 32}, 9 {64, 0, 0, 64}, 10 {128, 0, 0, 128}, 11 {192, 0, 192, 192}, 12 {255, 255, 255, 255}, 13}; 14 15float Fp[ 320 ][ 200 ]; // Новое поле 16float Fn[ 320 ][ 200 ]; // Предыдущее поле 17 18void init() { 19 20 srand(3); 21 for (int i = 0; i < 200; i++) 22 for (int j = 0; j < 320; j++) 23 Fp[j][i] = 0; 24 25 generate_palette(PALETTENUM, pal); 26} 27 28float xy(int x, int y) { 29 30 if (x < 0) x = -x; 31 if (y < 0) y = -y; 32 if (x >= 320) x = 639 - x; 33 if (y >= 200) y = 399 - y; 34 return Fn[x][y]; 35} 36 37// Генератор волн 38void waves() { 39 40 int i, j; 41 42 // Генераторы 43 if (mouse.st & LF_CLICK) Fn[ mouse.x ][ mouse.y ] = (rand()%256) - 16; 44 45 // Случайные капли 46 for (j = 0; j < 4; j++) Fn[ rand() % 320 ][ rand() % 200 ] = (rand() % 32); 47 48 // Релаксация, выше 1.0f не делать 49 float omega = 0.99; 50 float laplas; 51 52 // Основная функция 53 for (i = 0; i < 200; i++) { 54 for (j = 0; j < 320; j++) { 55 56 // Расчет лапласиана 57 laplas = xy(j-1, i+0); 58 laplas += xy(j+1, i+0); 59 laplas += xy(j+0, i-1); 60 laplas += xy(j+0, i+1); 61 62 // Дополнительная точность 63 laplas += xy(j-1, i-1); 64 laplas += xy(j+1, i+1); 65 laplas += xy(j-1, i+1); 66 laplas += xy(j+1, i-1); 67 laplas = (laplas / 8.0f); 68 69 // Итоговое значение 70 Fp[j][i] = laplas + omega*(Fn[j][i] - Fp[j][i]); 71 72 // Релаксация, чтобы волны успокаивались 73 Fp[j][i] *= 0.999f; 74 } 75 } 76 77 // Обмен полей 78 for (i = 0; i < 200; i++) 79 for (j = 0; j < 320; j++) { 80 float sw = Fp[j][i]; 81 Fp[j][i] = Fn[j][i]; 82 Fn[j][i] = sw; 83 } 84} 85 86// Перерисовать 87void redraw() { 88 89 for (int y = 0; y < 200; y++) { 90 for (int x = 0; x < 320; x++) { 91 92 int a = 128 + 12*(Fn[x][y]); 93 a = a < 1 ? 1 : (a > 255 ? 255 : a); 94 pset(x, y, a); 95 } 96 } 97} 98 99int main(int argc, char* argv[]) { 100 101 screen(13); 102 init(); 103 104 while (sdlevent(EVT_REDRAW)) { 105 106 waves(); 107 redraw(); 108 } 109 110 return 0; 111}