Алгоритм имитации пламени

flame

Реализовать алгоритм имитации пламени. Для вычисления цвета текущего пиксела использовать усредненное значение цветов окружающих пикселей.

Реализация алгоритма сводится к выводу на экран текущего кадра пламени хранящемся в массиве. Каждый элемент данного массива формируется следующим образом: берется сумма всех окружающих его элементов и делится на их количество (в приведенном ниже примере, количество точек равно четырем, но при их росте пропорционально увеличивается качество цвета точки). Также, ввиду формирования массива снизу вверх, усреднение суммы дает нужное нам затухание. Как результат мы получаем точку пламени на экране.

Порядок действий:
1. Устанавливаем графический режим, загружаем палитру, инициализируем буфер.
2. Преобразовываем буфер по уже известному нам алгоритму.
3. Выводим значение буфера на экран. При выходе - шаг 4, иначе идем на шаг 2.
4. Возврат графического режима.

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <time.h>
#include <stdlib.h>
 
#define GROWING // небольшое возгорание
#define MAX_GROW 150
 
#define VGA_SCREEN 0xa000
#define VIDEO_INT  0x10
#define VGA_MODE   0x13   // 320x200, 256 цветов
#define TEXT_MODE  0x03
 
#define DAC_WRITE_INDEX 0x03c8
#define DAC_DATA_REG    0x03c9
 
#define ESC_KEY 27
 
#define PALETTE_SIZE 256*3
 
#define V_WIDTH    80 // 80*4=320
#define V_HEIGHT   50 // 50*4=200
 
#define BUF_HEIGHT 80
#define BUF_WIDTH  80
 
unsigned char far *screen;      // указатель на экран(320x200)
int buf[BUF_HEIGHT][BUF_WIDTH]; // буфер
 
// палитра
char palette[PALETTE_SIZE]={
	   0,   0,   0,  0,  0, 24,  0,  0, 24,  0,  0, 28,
	   0,   0,  32,  0,  0, 32,  0,  0, 36,  0,  0, 40,
	   8,   0,  40, 16,  0, 36, 24,  0, 36, 32,  0, 32,
	  40,   0,  28, 48,  0, 28, 56,  0, 24, 64,  0, 20,
	  72,   0,  20, 80,  0, 16, 88,  0, 16, 96,  0, 12,
	 104,   0,   8,112,  0,  8,120,  0,  4,128,  0,  0,
	 128,   0,   0,132,  0,  0,136,  0,  0,140,  0,  0,
	 144,   0,   0,144,  0,  0,148,  0,  0,152,  0,  0,
	 156,   0,   0,160,  0,  0,160,  0,  0,164,  0,  0,
	 168,   0,   0,172,  0,  0,176,  0,  0,180,  0,  0,
	 184,   4,   0,188,  4,  0,192,  8,  0,196,  8,  0,
	 200,  12,   0,204, 12,  0,208, 16,  0,212, 16,  0,
	 216,  20,   0,220, 20,  0,224, 24,  0,228, 24,  0,
	 232,  28,   0,236, 28,  0,240, 32,  0,244, 32,  0,
	 252,  36,   0,252, 36,  0,252, 40,  0,252, 40,  0,
	 252,  44,   0,252, 44,  0,252, 48,  0,252, 48,  0,
	 252,  52,   0,252, 52,  0,252, 56,  0,252, 56,  0,
	 252,  60,   0,252,  60,  0,252, 64,  0,252, 64,  0,
	 252,  68,   0,252,  68,  0,252, 72,  0,252, 72,  0,
	 252,  76,   0,252,  76,  0,252, 80,  0,252, 80,  0,
	 252,  84,   0,252,  84,  0,252, 88,  0,252, 88,  0,
	 252,  92,   0,252,  96,  0,252, 96,  0,252,100,  0,
	 252, 100,   0,252, 104,  0,252,104,  0,252,108,  0,
	 252, 108,   0,252, 112,  0,252,112,  0,252,116,  0,
	 252, 116,   0,252, 120,  0,252,120,  0,252,124,  0,
	 252, 124,   0,252, 128,  0,252,128,  0,252,132,  0,
	 252, 132,   0,252, 136,  0,252, 136,   0,252, 140,   0,
	 252, 140,   0,252, 144, 0,252, 144,   0,252, 148,   0,
	 252, 152,   0,252, 152, 0,252, 156,   0,252, 156,   0,
	 252, 160,   0,252, 160, 0,252, 164,   0,252, 164,   0,
	 252, 168,   0,252, 168, 0,252, 172,   0,252, 172,   0,
	 252, 176,   0,252, 176, 0,252, 180,   0,252, 180,   0,
	 252, 184,   0,252, 184, 0,252, 188,   0,252, 188,   0,
	 252, 192,   0,252, 192, 0,252, 196,   0,252, 196,   0,
	 252, 200,   0,252, 200, 0,252, 204,   0,252, 208,   0,
	 252, 208,   0,252, 208, 0,252, 208,   0,252, 208,   0,
	 252, 212,   0,252, 212,   0,252, 212,   0,252, 212,   0,
	 252, 216,   0,252, 216,   0,252, 216,   0,252, 216,   0,
	 252, 216,   0,252, 220,   0,252, 220,   0,252, 220,   0,
	 252, 220,   0,252, 224,   0,252, 224,   0,252, 224,   0,
	 252, 224,   0,252, 228,   0,252, 228,   0,252, 228,   0,
	 252, 228,   0,252, 228,   0,252, 232,   0,252, 232,   0,
	 252, 232,   0,252, 232,   0,252, 236,   0,252, 236,   0,
	 252, 236,   0,252, 236,   0,252, 240,   0,252, 240,   0,
	 252, 240,   0,252, 240,   0,252, 240,   0,252, 244,   0,
	 252, 244,   0,252, 244,   0,252, 244,   0,252, 248,   0,
	 252, 248,   0,252, 248,   0,252, 248,   0,252, 252,   0,
	 252, 252,   4,252, 252,   8,252, 252,  12,252, 252,  16,
	 252, 252,  20,252, 252,  24,252, 252,  28,252, 252,  32,
	 252, 252,  36,252, 252,  40,252, 252,  40,252, 252,  44,
	 252, 252,  48,252, 252,  52,252, 252,  56,252, 252,  60,
	 252, 252,  64,252, 252,  68,252, 252,  72,252, 252,  76,
	 252, 252,  80,252, 252,  84,252, 252,  84,252, 252,  88,
	 252, 252,  92,252, 252,  96,252, 252, 100,252, 252, 104,
	 252, 252, 108,252, 252, 112,252, 252, 116,252, 252, 120,
	 252, 252, 124,252, 252, 124,252, 252, 128,252, 252, 132,
	 252, 252, 136,252, 252, 140,252, 252, 144,252, 252, 148,
	 252, 252, 152,252, 252, 156,252, 252, 160,252, 252, 164,
	 252, 252, 168,252, 252, 168,252, 252, 172,252, 252, 176,
	 252, 252, 180,252, 252, 184,252, 252, 188,252, 252, 192,
	 252, 252, 196,252, 252, 200,252, 252, 204,252, 252, 208,
	 252, 252, 208,252, 252, 212,252, 252, 216,252, 252, 220,
	 252, 252, 224,252, 252, 228,252, 252, 232,252, 252, 236,
	 252, 252, 240,252, 252, 244,252, 252, 248,252, 252, 252
};
 
void set_mode    (int mode);
void set_palette ();
void init_buf    ();
 
// инициализируем буфер
void init_buf ()
{
  int i=0, j=0;
  for (; i<BUF_HEIGHT; i++)
    for (; j<BUF_WIDTH; j++)
      buf[i][j]=0;
}
 
// загружаем палитру
void set_palette ()
{
  int i;
  outportb(DAC_WRITE_INDEX, 0);
  for (i=0; i<PALETTE_SIZE; i++)
    {
      palette[i] = palette[i] >> 2;
      outportb(DAC_DATA_REG, palette[i]);
    }
}
 
// выставляем графический режим
void set_mode (int mode)
{
  union REGS regs;
  regs.x.ax = mode;
  int86(VIDEO_INT, &regs, &regs);
}
 
// огонь...
int main ()
{
  int i,j,k,l;
  int d=0,g=0;
  double v=1;
 
  char key = ' ';
 
  set_mode(VGA_MODE);
  set_palette();     
  randomize();       
 
  time_t t;
  srand((unsigned)time(&t));
 
  init_buf();
 
  // ESC для выхода...
  while (key != ESC_KEY)
    {
 
    // Преобразовываем буфер(кадр)
 
    for(i=1;i<BUF_HEIGHT;i++)
      for(j=0;j<BUF_WIDTH;j++)
	{
	  if      (j==0)   buf[i-1][j]=(buf[i][j]+buf[i-1][BUF_WIDTH-1]+buf[i][j+1]+buf[i+1][j]) / 4;
	  else if (j==(BUF_WIDTH-1)) buf[i-1][j]=(buf[i][j]+buf[i][j-1]+buf[i+1][0]+buf[i+1][j]) / 4;
	  else                       buf[i-1][j]=(buf[i][j]+buf[i][j-1]+buf[i][j+1]+buf[i+1][j]) / 4;
 
	  if     (buf[i][j] > 11)  buf[i][j]= buf[i][j] - 12;
	  else if(buf[i][j] >  3)  buf[i][j]= buf[i][j] - 4;
	  else
	    {
	      if(buf[i][j] > 0) buf[i][j]--;
	      if(buf[i][j] > 0) buf[i][j]--;
	      if(buf[i][j] > 0) buf[i][j]--;
	    }
	}
 
      // Новая нижняя граница
      d=0;
      for (j=0; j<BUF_WIDTH; j++)
	{
	  if (random(10) < 5) d = random(2) * 256;
	  buf[BUF_HEIGHT -2][j] = d+g;
	  buf[BUF_HEIGHT -1][j] = d;
	}
 
#ifdef GROWING
      g+=int(v);
      if (g>MAX_GROW) v=-random(2);
      else if (g==0) v=+random(2);
#endif
 
      // Выводим текущий кадр на экран...
      screen = (char far *)MK_FP(VGA_SCREEN, 0);
      for (i=0; i<V_HEIGHT; i++)
	for (k=0; k<4; k++)
	  for (j=0; j<V_WIDTH; j++)
	    for (l=0; l<4; l++)
	      {
		*screen = (unsigned char)buf[i][j];
		screen++;
	      }
 
      if (kbhit())
	key = getch();
    }
 
  set_mode(TEXT_MODE);
 
  return 0;
}

Ключевые слова: 
огонь пламя эффекты
ВложениеРазмер
fire.rar21.98 кб