burn.c

来自「linux下的任天堂模拟器代码。供大家参考。」· C语言 代码 · 共 198 行

C
198
字号
/*Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )http://www.zsnes.comhttp://sourceforge.net/projects/zsneshttps://zsnes.bountysource.comThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*   Fire effects implementation by Frank Jan Sorensen, Joachim Fenkes,   Stefan Goehler, Jonas Quinn, et al.*/#include <stdlib.h>#include <string.h>#include <math.h>#include <time.h>#ifndef M_PI#ifndef PI#define M_PI 3.1415926535897932384626433832795#else#define M_PI PI#endif#endif#define BUF_WIDTH 288#define BUF_HEIGHT 224const int rootrand = 20;	/* Max/Min decrease of the root of the flames */const int decay = 5;		/* How far should the flames go up on the screen? This MUST be positive - JF */const int miny = 1;		/* Starting line of the flame routine. (should be adjusted along with MinY above) */const int smooth = 1;   /* How discrete can the flames be? */const int minfire = 50; /* limit between the "starting to burn" and the "is burning" routines */const int xstart = 0;  /* Starting position on the screen, should be divisible by 4 without remainder! */const int xend = 287;  /* Guess! */const int width = 1 + 287;const int maxcolor = 110; /* Constant for the MakePal procedure */const int fireincrease = 3; /* 3 = Wood, 90 = Gasoline */typedef struct colorvalue{  unsigned char r, g, b;} colorvalue;typedef colorvalue vgapalettetype[256];/* Converts (Hue, Saturation, Intensity) -> (RGB) */void hsi2rgb(double h, double s, double i, struct colorvalue *c){  double t;  double rv, gv, bv;  t = h;  rv = 1 + s * sin(t - 2 * M_PI / 3);  gv = 1 + s * sin(t);  bv = 1 + s * sin(t + 2 * M_PI / 3);  t = 255.999 * i / 2;  c->r = (unsigned char) floor(rv * t);  c->g = (unsigned char) floor(gv * t);  c->b = (unsigned char) floor(bv * t);}void genpal(){  int i;  vgapalettetype pal;  memset(pal, 0, 3);  for( i=1; i <= maxcolor; i ++)  {    hsi2rgb(4.6-1.5*i/maxcolor,(double)(i)/maxcolor,(double)(i)/maxcolor,&pal[i]);  }  for( i=maxcolor; i <= 255; i ++)  {    pal[i]=pal[i-1];    {      struct colorvalue *with = &pal[i];      if (with->r<255) with->r += 1;      if (with->r<255) with->r += 1;      if ((~i & 1) && (with->g<215)) with->g += 1;      if ((~i & 1) && (with->b<255)) with->b += 1;    }  }}int started = 0;#define Randomize()#define randint(a) (rand() % (a))#define randreal() (((double)rand()) / ((double)RAND_MAX))#define rand1(a) ((randint(a*2+1))-a)unsigned char flamearray[BUF_WIDTH];int morefire;extern unsigned char *vidbuffer;/* damn, this seems like such a waste */static unsigned char pt[BUF_WIDTH * BUF_HEIGHT];void DrawBurn(){  int i,j;  int x,p;  int v;  if (!started)  {    started = 1;    for( i=xstart; i <= xend; i++)    {      flamearray[i]=0;    }    Randomize();    morefire=1;    memset(pt, 0, BUF_HEIGHT * BUF_WIDTH);  }  /* Put the values from FlameArray on the bottom line of the screen */  memcpy(pt+((BUF_HEIGHT-1)*BUF_WIDTH)+xstart,flamearray, width);  /* This loop makes the actual flames */  for( i=xstart; i <= xend; i++)  {    for( j=miny; j <= (BUF_HEIGHT-1); j ++)    {      v = pt[j*BUF_WIDTH + i];      if ((v==0) ||          (v<decay) ||          (i<=xstart) ||          (i>=xend))        pt[(j-1)*BUF_WIDTH + i] = 0;      else        pt[((j-1)*BUF_WIDTH) + (i-(randint(3)-1))] = v - randint(decay);    }  }  /* Match? */  if (randint(150)==0)  {    memset(flamearray + xstart + randint(xend-xstart-5),255,5);  }  /* This loop controls the "root" of the    flames, i.e. the values in FlameArray. */  for( i=xstart; i <= xend; i++)  {    x=flamearray[i];    if (x<minfire)    /* Increase by the "burnability" */    {      /* Starting to burn: */      if (x>10)  x += randint(fireincrease);    }    else    /* Otherwise randomize and increase by intensity (is burning) */      x += rand1(rootrand)+morefire;    if (x>255)  x=255;    /* X Too large? */    flamearray[i]=x;  }  /* Smoothen the values of FrameArray to avoid "discrete" flames */  p=0;  for( i=xstart+smooth; i <= xend-smooth; i++)  {    x=0;    for( j=-smooth; j <= smooth; j++) x += flamearray[i+j];    flamearray[i] = x / ((smooth << 1) + 1);  }  for (x=0; x < BUF_WIDTH*BUF_HEIGHT; x++)  {    i = vidbuffer[x];    j = pt[x] >> 3;    if (j > i) { vidbuffer[x] = j; }    else { vidbuffer[x] = ((i + j) >> 1) + 1; }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?