§ Демонстрация

Переписал программу на 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}