{
Public:
CFireRoutine(); //constructor
virtual ~ CFireRoutine(); //Destructor of virtual state
//functions (public)
void init fire(); //initialization
void ClrHotSpots(); //Clear the burning point
void InitPallette(); //Initialize the palette
void set hotspots(); //Set the ignition point
void MakeLines(); //Generate scan lines
//Presentation (video memory, width, height)
void Render(DWORD * pvideomememory,
int iwidth,
int iheight);
//mean (at x, y points) (pixel mean? )
Average value of unsigned characters (int x, int y);
//props
Int m _ iFlameHeight// flame height
Int m _ iWidth// width
Int m _ iHeight//Height (should be the height of the drawing area)
//the source of the flame, that is, the y coordinate from the ignition point.
Int m _ iFireSource// y position of luminous point
Int m _ iFireChance// combustion probability
Int m _ iAvgFlameWidth// average flame width
Int m _ iAlpha//α/alpha (depth)
COLORREF m _ fire colors[4]; //Flame color
BYTE * m _ pFireBits// flame data
DWORD m _ pPalletteBuffer[256]; //Palette
Long * m _ pYIndexes// color index
};
//Melting slurry:
CPlasmaRoutine class
{
Public:
CPlasmaRoutine(); //constructor
virtual ~ CPlasmaRoutine(); //Virtual destructor
//method
void SetDefaultValues(VARIANT * pExtParms); //Set the default parameter value (external variable)
void initialize plasma(VARIANT * pExtParms); //Initialize the magma parameter
void Create(int iWidth,int I height); //Generate magma according to the view.
Void Render(DWORD* pBits,//Renders according to pixel position, view width, height and scan line.
int iwidth,
Height,
int iline length);
//Set the RGB value of the color index.
void SetRGB(int iIndex,int R,int G,int B);
void InitCostBLTable(); //Initialize the wear balance table? Does BL mean balance? I don't know, not contrast and brightness, but color saturation. There seems to be none.
void InitPallette(); //Initialize the palette
void calc plasma(); //calculate magma
//Start by color, end by color, create gradient color by color step, and store it in the buffer.
void create gradient(COLORREF clr start,COLORREF clrEnd,long lSteps,COLORREF * p buffer);
//props
Int m _ iWidth// view width
Int m _ iHeight// view height
Int m _ iAlpha// View depth
BYTE * m _ pPlasmaBits//magma sequence buffer
DWORD m _ pPalletteBuffer[256]; //Palette
int m _ icost bl[256]; //Loss balance sheet
COLORREF m _ plasma colors[ 16]; //yep 16 Colors needed to generate a palette ... 16 colors are used to generate a palette.
//The following should be the four control points and vector coordinates of Bezier curve used for curve fitting.
Unsigned characters m_a 1, m_a2, m_a3, m_a4, m_b 1, m_b2, m_b3, m _ b4.
int m _ imodifier 1;
int m _ iModifier2
int m _ iModifier3
int m _ iModifier4
//Bidirectional modifier (vector formed by two-point pulling)
int m _ ixmodifier 1;
int m _ iXModifier2
int m _ iy modifier 1;
int m _ iYModifier2
};
//fireroutine.cpp: implementation of cfireroutine class.
//
//////////////////////////////////////////////////////////////////////
# contains "stdafx.h"
# contains "FireRoutine.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS _ FILE[]= _ _ FILE _ _;
# Define a new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
//Construct/destroy the constructor and initialize all parameters. Note that the initial value of fire source is 2, and the initial value of combustion probability is 10.
//////////////////////////////////////////////////////////////////////
CFireRoutine::CFireRoutine()
{
m _ I width = 0;
m _ iHeight = 0;
m _ pFireBits = NULL
m _ pYIndexes = NULL
m _ ifi resource = 2;
m _ ifirecharce = 10;
m _ iFlameHeight = 50
m _ iAlpha = 255
m_FireColors[0] = RGB(0,0,0); //Black
m_FireColors[ 1] = RGB(255,0,0); //Red
m_FireColors[2] = RGB(255,255,0); //yellow
m_FireColors[3] = RGB(255,255,255); //White
m _ iAvgFlameWidth = 35
}
//destructor, if the color index and rendering buffer exist, log out.
CFireRoutine::~CFireRoutine()
{
if(m_pFireBits! = empty)
delete[]m _ pFireBits;
if(m_pYIndexes! = empty)
Delete [] m _ pyindexes;
m _ pFireBits = NULL
m _ pYIndexes = NULL
}
void CFireRoutine::InitFire()
{
//Remove anything prepared there to initialize the flame. If there is a color index and rendering buffer, log out first.
if(m_pFireBits! = empty)
delete[]m _ pFireBits;
if(m_pYIndexes! = empty)
Delete [] m _ pyindexes;
//Height plus three automatically adds three.
m _ ih height+= 3;
m _ py indexes = new long[m _ iHeight]; //An array of long integers with flame height as the length during color indexing.
M_pFireBits = new byte [m _ iwidth * m _ ihight]; //The rendering buffer is a character array with a length of w * h..
//Clear the Fire bit to set the flame buffer to zero.
memset(m_pFireBits,0,(m _ I width * m _ I height));
//Pre-calculate all Y indexes ... Before calculation, initialize the color buffer value to each element = width * height.
for(int y = m _ iHeight; y & gt0; y -)
m _ py indexes[y]= y * m _ I width;
//Create our color palette
InitPallette(); //Initialize the palette
ClrHotSpots(); //Clear the burning point
}
//Clearing the burning point means clearing a line in the rendering buffer. What line is it? It's the line that the fire source points to in the color index.
void CFireRoutine::ClrHotSpots()
{
//Clear the fire line
memset(& amp; m _ pFireBits[m _ py indexes[m _ ifi resource]],0,m _ I width);
}
//Initialize the color palette. You may need to understand the concept of palette first: although the picture may be colored, if each pixel
//are all stored in three bytes of RGB, so the cost is too high. The palette is based on the assumption that this picture is a color picture, but after color analysis,
//There are only 256 colors commonly used in pictures, so a byte can represent a pixel, but the value of this byte refers to
//Not the color vector of RGB, but the code of 256 colors, which is the color palette of this picture.
void CFireRoutine::InitPallette()
{
//Create a gradient between all the colors of the fire ... All the colors used to create a transition color for our flame.
long iCount = 0;
COLORREF clrStart
COLORREF clrEnd
for(int iColor = 1; iColor & lt4; IColor++) // Four color definitions of flame
{
clr start = m _ fire colors[iColor- 1]; //Set the starting color of the transition color.
clrEnd = m _ fire colors[iColor]; //Set the ending color of the transition color.
int r,g,b; //Distance first, then the initial value. Calculate the distance first, then the value.
Floating point rStep, gStep, bStep// step size of each color//transition step size value of each color.
//Get the color difference to get the initial color and transition color difference of three colors RGB.
r =(getr value(clrEnd)-getr value(clr start));
g =(GetGValue(clrEnd)-GetGValue(clr start));
b =(getb value(clrEnd)-getb value(clr start));
int nSteps = max(abs(r),max(abs(g),ABS(b))); //The number of transition steps is the largest color difference among RGB, red, green and blue.
float f step =(float)(255/3)/(float)n steps; //Convert the color difference step value to a floating point number.
//Calculate the step size of each color.
rStep = r/(float)ns teps; //Find the color difference step value of each color component.
gStep = g/(float)ns teps;
bStep = b/(float)ns teps;
//Reset the color to the starting position to set the color as the initial color of the progressive color.
r = getr value(clr start);
g = GetGValue(clr start);
b = getb value(clr start);
for(int iOnBand = 0; IOnBand & ltnStepsIOnBand++) // Calculate the actual value of each color in the whole gradient according to RGB.
{
//COLORREF color = RGB(r+rStep * ion band,g + gStep*iOnBand,b+bStep * ion band);
COLORREF color = RGB(b+bStep * ion band,g + gStep*iOnBand,r+rStep * ion band);
long lIndex =(int)(ion band * f step);
if(lIndex+((iColor- 1)* 85)& lt; 255)
m _ pPalletteBuffer[lIndex+((iColor- 1)* 85)]= color; //Put the calculation results into the color palette.
}
}
//Step on the second color a little ... transition to the end color, and the content generated by the later color is basically the same as above.
clr start = m _ fire colors[0];
clrEnd = m _ fire colors[ 1];
for(int kj = 0; kj & ltm _ iFlameHeightkj++)
m _ pPalletteBuffer[kj]= 0;
int r,g,b; //First the distance, then the starting value.
Floating point rStep, gStep, bStep// step size of each color.
//Get the color difference
r =(getr value(clrEnd)-getr value(clr start));
g =(GetGValue(clrEnd)-GetGValue(clr start));
b =(getb value(clrEnd)-getb value(clr start));
int nSteps = max(abs(r),max(abs(g),ABS(b)));
float f step =(float)(85-m _ iFlameHeight)/(float)n steps;
//Calculate the step size of each color.
rStep = r/(float)ns teps;
gStep = g/(float)ns teps;
bStep = b/(float)ns teps;
//Reset the color to the starting position.
r = getr value(clr start);
g = GetGValue(clr start);
b = getb value(clr start);
for(int iOnBand = 0; iOnBand & ltnStepsiOnBand++)
{
//COLORREF color = RGB(r+rStep * ion band,g + gStep*iOnBand,b+bStep * ion band);
COLORREF color = RGB(b+bStep * ion band,g + gStep*iOnBand,r+rStep * ion band);
long lIndex =(int)(ion band * f step);
m _ pPalletteBuffer[lIndex+(85-m _ iFlameHeight)]= color; //Fill in the color value
}
}
//Get a macro of random integers within the specified range */This is a macro that takes random numbers according to the range.
#define getrandom( min,max)((rand()%(int)(((max)+ 1)-(min))+(min))
# include & lttime.h & gt
Voidcfire routine:: Set hotspots()// Set the ignition point.
{
ClrHotSpots(); //First, define the ignition point.
//m_iAvgFlameWidth
long l position = 0; //Accumulate according to the horizontal axis position until the width limit is reached.
while(l position & lt; m_iWidth)
{
//See if we should make a flame.
if (getrandom(0, 100)& lt; M _ ifirecharce)///Take a random number to see if it is within the combustion probability range. If not, skip it.
{
//Get the flame width
long lflame width = get random( 1,m _ iAvgFlameWidth); //Obtain a flame width at random.
for(int I = 0; I & ltlFlameWidthi++)
{
if(l position & lt; M_iWidth) // If the position is within the screen, set a ignition point.
{
m _ pFireBits[m _ py indexes[m _ ifi resource]+lPosition]= 254; //Set hot spots!
l position++;
}
}
}
l position++;
}
//for(x = 0; x & ltm _ iWidthx++)
// {
// if (getrandom(0, 100)& lt; M _ charging)
// {
// }
// }
}
Voidcfiire routine:: make lines()// Generate rendered scan lines.
{
int x,y;
for(x = 0; X<m _ iWidthX++) // Loop horizontally, from left to right of the screen.
{
for(y = m _ ifi resource; y & ltm _ ih height- 1; Y++) // Longitudinal circulation, from fire source to flame height
//for(y = m _ I height; y & gtm _ iFireSourcey -)
{
//m _ pFireBits[m _ py indexes[y- 1]+x]= Average(x,y);
m _ pFireBits[m _ py indexes[y+ 1]+x]= Average(x,y); //The flame value is the average of the scan lines.
}
}
}
Unsigned char CFireRoutine::Average(int x, int y)
{
Unsigned character ave _ color
Unsigned char ave 1, ave2, ave3, ave4, ave5, ave6, ave7.
//Make sure we are not in the last line ... As long as it is not the last scan line, the average value is calculated as follows.
if(y == m_iHeight)
ave 1 = m _ pFireBits[m _ py indexes[y- 1]+x];
other
ave 1 = m _ pFireBits[m _ py indexes[y+ 1]+x];
//The method of scanning the average value of lines, take a transverse ellipse with x, y as the center, a small radius of 1 and a large radius of 2, get the color from this range, and then calculate the average value:
//It is basically the style shown below: format: take a dot (coordinate).
/*
1#(x,y+ 1)
6#(x-2,y) 4#(x- 1,y) 7#(x,y) 3#(x+ 1,y) 5#(x+2,y)
2#(x,y- 1)
*/
ave 2 = m _ pFireBits[m _ py indexes[y- 1]+x];
ave 3 = m _ pFireBits[m _ py indexes[y]+x+ 1];
ave 4 = m _ pFireBits[m _ py indexes[y]+x- 1];
ave 5 = m _ pFireBits[m _ py indexes[y]+x+2];
ave 6 = m _ pFireBits[m _ py indexes[y]+x-2];
ave 7 = m _ pFireBits[m _ py indexes[y]+x];
ave _ color =(ave 1+ave 2+ave 3+ave 4+ave 5+ave 6+ave 7)/7;
//Find the color average and return it.
return(ave _ color);
}
//Render according to the video memory.
void CFireRoutine::Render(DWORD * pvideomememory,
int iwidth,
Internal height
)
{
set hotspots(); //Generate random hot spots and generate combustion points.
make lines(); //Perform all mathematical calculations and screen updates//Generate scan lines and update the screen.
//Now, I just transfer the block to the video memory//BitBlt buffer copy the video memory.
Unsigned char * psrcbitlin//= m _ pfire bits+(m _ iwidth * 3); //Get rid of our fire source//Get the fire source.
BYTE * dst//=(BYTE *)Dib-& gt; PVideoMemory memory;
Byte r;
Byte g;
Byte b;
for(int I = 0; I<m _ ihheight-3; I++) // Progressive scanning
{
Dst = (byte *)&; pvideomememory[(I width * I)]; //Get the current line of the video
pSrcBitlin = & ampm _ pFireBits[m _ py indexes[I+3]]; //Set the scan line data pointer
for(int x = 0; x & ltm _ iWidthx++)
{
//Synthetic color, pay attention to the RGB component of the index color, then add depth and saturation, and then offset.
r = getr value(m _ pPalletteBuffer[pSrcBitlin[x]]);
g = GetGValue(m _ pPalletteBuffer[pSrcBitlin[x]]);
b = getb value(m _ pPalletteBuffer[pSrcBitlin[x]]);
dst[0]=(BYTE)(((r-dst[0])* m _ I alpha+(dst[0]& lt; & lt8))& gt; & gt8);
dst[ 1]=(BYTE)(((g-dst[ 1])* m _ I alpha+(dst[ 1]& lt; & lt8))& gt; & gt8);
dst[2]=(BYTE)(((b-dst[2])* m _ I alpha+(dst[2]& lt; & lt8))& gt; & gt8);
dst+= 4;
}
}
}
About the source code of magma and water wave, the concept is similar. The color model is established first, and then matched to the buffer. After careful comparison, we can understand them.