Лисья Нора

Оглавление


§ Краткое описание

Принцип работы эффекта воды схож с тем принципом, что и эффект огня, но есть различия в методе расчета клеточной функции.

§ Программный код

water.png
#include <qblib.h>
 
// Исходная палитра
static const unsigned char pal[5][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 load()
{
srand(3);
for (int i = 0; i < 200; i++)
for (int j = 0; j < 320; j++)
Fp[j][i] = 0;
 
palette(pal, 5);
}
 
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;
 
// Случайные капли
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();
load();
 
while (loop(50)) {
waves();
redraw();
}
 
save("water.ppm");
 
return quit();
}