Código fuente de coincidencia de colores transparente
{
Público:
CFireRoutine(); //Constructor
virtual ~ CFireRoutine ( ); // Destructor de estado virtual
// Funciones (públicas)
void init fire(); //Inicialización
void ClrHotSpots( ); /Borrar puntos de acceso
void InitPallette(); //Inicializar la paleta
void set hotspots(); //Establecer puntos de acceso
void MakeLines(); /Generar líneas de escaneo
//Render (memoria de video, ancho, alto)
void Render(DWORD * pvideomememory,
int iwidth,
int iheight);
//Valor medio (en el punto x, y) (¿media de píxeles?)
Media de caracteres sin signo (int x, int y); p>
//Props
int m _ iFlameHeight//Alto de la llama
int m _ iWidth//Ancho
int m _ iHeight// Altura (debe ser la altura del área de dibujo)
//La fuente de la llama, que es la coordenada Y desde el punto de ignición.
int m _ iFireSource//Posición Y del punto luminoso
int m _ iFireChance//Probabilidad de combustión
int m _ iAvgFlameWidth//Ancho medio de llama
int m _ iAlpha//α(profundidad)
COLORREF m _ colores de fuego[4];//Color de fuego
BYTE * m _ pFireBits/ / Datos de llama
DWORD m_pPalletteBuffer[256];//Paleta
long * m_pYIndexes//Índice de color
};
/ /Lodo de fusión:
Clase CPlasmaRoutine
{
Público:
CPlasmaRoutine() //Función de construcción
virtual ~ CPlasmaRoutine(); //Destructor virtual
//Método
void SetDefaultValues(VARIANT * pExtParms); //Establecer el valor de los parámetros predeterminados (variable externa)
void inicializar plasma(VARIANT * pExtParms); //Inicializar parámetros de magma
void Create(int iWidth, int I height //Generar magma según la vista
Void Render(DWORD* pBits, //Renderizado basado en la posición del píxel, ancho de vista, alto y línea de escaneo.
int iwidth,
Alto,
int iline length);
//Establece el valor RGB del índice de color.
void SetRGB(int iIndex, int R, int G, int B);
void InitCostBLTable(); // ¿Inicializar la tabla de balance de desgaste? ¿BL significa equilibrio? No lo sé, no es contraste ni brillo, es saturación de color. Parece que no hay ninguno.
void InitPallette(); //Inicializa la paleta
void calc plasma(); //Calcula magma
//Comienza por color, presiona color At Al final, cree un color degradado de acuerdo con el paso de color y guárdelo en el búfer.
void create gradient(COLORREF clr start, COLORREF clrEnd, long lSteps, COLORREF * p buffer
//Props
int m _ iWidth// Ancho de vista
int m _ iHeight//Alto de vista
int m _ iAlpha//Profundidad de vista
BYTE * m _ pPlasmaBits//búfer de secuencia de magma
DWORD m _ pPalletteBuffer[256]; //Paleta
int m _ icost bl[256]; //Tabla de saldo de pérdidas
COLORREF m _plasma colours[ 16]; //sí16 Los colores necesarios para generar la paleta... Se utilizan 16 colores para generar la paleta.
//Los siguientes deben ser los cuatro puntos de control y las coordenadas vectoriales de la curva de Bézier utilizada para el ajuste de la curva.
Caracteres sin firmar m_a1, m_a2, m_a3, m_a4, m_b1, m_b2, m_b3, m_b4
int m_imodifier 1;
int m_ iModifier2
int m _ iModifier3
int m _ iModifier4
//Modificador bidireccional (vector formado tirando de dos puntos)
int m _ ixmodifier 1; /p>
int m _ iXModifier2
int m _ iy modificador 1
int m _ iYModifier2
} ;
//rutina de fuego CPP: Implementación de la clase de rutina de fuego.
//
/////////////////////////////////// // /////////////////////////////////////////////// p>
#Contiene "stdafx.h"
#Contiene "FireRoutine.h"
#ifdef _DEBUG
#undef THIS_FILE
carácter estático ESTE _ ARCHIVO[]= _ _ ARCHIVO _ _;
#Definir nuevo DEBUG_NEW
#endif
////// /////////// /////////////////////////////////////// ////////////// ///
//Construir/destruir el constructor e inicializar todos los parámetros. Tenga en cuenta que el valor inicial de la fuente del incendio es 2 y el valor inicial de la probabilidad de combustión es 10.
//////////////////////////////////////////// // ////////////////////////////
CFireRoutine::CFireRoutine()
{ p>
m _ I ancho = 0
m _ iHeight = 0
m _ pFireBits = NULL
m _ pYIndexes = NULL
m _ ifi recurso = 2
m _ ifirecharce = 10
m _ iFlameHeight = 50
m _ iAlpha = 255
m_FireColors[0] = RGB(0,0,0);//Negro
m_FireColors[1] = RGB(255,0,0);// Rojo
p>
m_FireColors[2] = RGB(255, 255, 0); //Amarillo
m_FireColors[3] = RGB(255, 255, 255) ; //Blanco
m _ iAvgFlameWidth = 35
}
//Destructor, cierre sesión si existe un índice de color y un búfer de renderizado.
CFireRoutine::~CFireRoutine()
{
if(m_pFireBits!=null)
eliminar[]m _ pFireBits;
if(m_pYIndexes!=null)
Eliminar[]m_py índices;
m_pFireBits = NULL
m_ pYIndexes = NULL p>
}
void CFireRoutine::InitFire()
{
//Elimina todo lo preparado allí para inicializar Flame, si hay un color. indexar y renderizar el búfer, primero cierre la sesión.
if(m_pFireBits!=null)
eliminar[]m_pFireBits;
if(m_pYIndexes!=null)
Eliminar [] m _ py indexes;
//Agrega tres a la altura y automáticamente agrega tres.
m _ ih height+= 3;
m _ py indexes = new long[m _ iHeight] //El índice de color es una matriz entera larga con la altura de la llama; como la longitud.
m_pFireBits = new bytes [m_I ancho * m_I alto]; //El búfer de renderizado es una matriz de caracteres de longitud w * h.
//Borre el bit de Fuego para establecer el buffer de llama en cero.
memset(m_pFireBits, 0, (m _ I ancho * m _ I alto));
//Realizar un cálculo previo de todos los índices y... Antes del cálculo, coloque El valor del búfer de color se inicializa como cada elemento = ancho * alto.
for(int y = m _ iHeight; y & gt0;y -)
m _ py indexes[y]= y * m _ I ancho
//Crea nuestra paleta
InitPallette(); //Inicializa la paleta
ClrHotSpots(); //Borra los puntos ardientes
} p>
//Borrar Randian significa borrar una línea en el búfer de renderizado.
¿Qué línea es? Es la línea en el índice de color hacia donde apunta la fuente del fuego.
void CFireRoutine::ClrHotSpots()
{
//Borrar FireWire
memset(& m _ pFireBits[m _py indexes [recurso m_ifi]], 0, ancho m_I);
}
//Inicializa la paleta. Es posible que primero deba comprender el concepto de paleta: aunque la imagen puede estar en color, si cada píxel
// se almacena en tres bytes de RGB, el costo es demasiado alto. La paleta de colores se basa en el supuesto de que esta imagen sigue siendo una imagen en color, pero después del análisis del color,
// Solo hay 256 colores comúnmente utilizados en las imágenes, por lo que un byte puede representar un píxel, pero este byte El valor se refiere a
//No es el vector de color RGB, sino el código de 256 colores, que es la paleta de esta imagen.
void CFireRoutine::InitPallette()
{
//Crea un degradado entre todos los colores del fuego... para crear para nuestras llamas Todos colores de colores de transición.
long iCount = 0;
COLORREF clrStart
COLORREF clrEnd
for(int iColor = 1; iColor & lt4;IColor++) //Cuatro definiciones de color de llama
{
clr start = m _ fire colours[iColor-1] //Establece el color inicial del color de transición.
clrEnd = m_fire Colors[iColor] //Establece el color final del color de transición.
int r, g, b; // Primero la distancia, luego el valor inicial. Primero calcula la distancia y luego el valor.
Punto flotante rStep, gStep, bStep//El tamaño del paso de cada color//El valor del paso de transición de cada color.
//Obtenga la diferencia de color para obtener el color inicial y la diferencia de color de transición de tres colores RGB.
r =(getr valor(clrEnd)-getr valor(clr inicio));
g =(GetGValue(clrEnd)-GetGValue(clr inicio)
b =(getb valor(clrEnd)-getb valor(clr inicio));
int nSteps = max(abs(r), max(abs(g),ABS(b))) ; //El número de pasos de transición es el que tiene la mayor diferencia de color entre RGB, rojo, verde y azul.
float f step =(float)(255/3)/(float)n pasos; //Convierte el valor del paso de diferencia de color en un número de punto flotante.
//Calcule el tamaño del paso de cada color
rStep = r/(float)ns teps; //Encuentre el valor del paso de diferencia de color de cada componente de color.
gStep = g/(float)ns teps;
bStep = b/(float)ns teps;
//Restablecer el color a la posición inicial establece el color al color inicial del color degradado.
r = getr valor(clr inicio);
g = GetGValue(clr inicio);
b = getb valor(clr inicio); >
for(int iOnBand = 0; iOnBand & ltnStepsIOnBand++) //Calcule el valor real de cada color en todo el degradado según RGB.
{
//COLORREF color = RGB(r+rStep * banda de iones, g + gStep*iOnBand, b+bStep * banda de iones);
COLORREF color = RGB(b+bPaso * banda de iones, g + gPaso*iOnBand, r+rPaso * banda de iones);
long lIndex =(int)(banda de iones * paso f);
if(lIndex+((iColor-1)* 85)& lt; 255)
m _ pPalletteBuffer[lIndex+((iColor-1)* 85)]= color; El resultado se pone en la paleta.
}
}
//Pise ligeramente el segundo color... transición al color final, y el contenido generado por los colores posteriores es básicamente lo mismo que el anterior.
clr start = m _ colores de fuego[0];
clrEnd = m _ colores de fuego[1]
for(int kj = 0; kj & ltm _ iFlameHeightkj++)
m _ pPalletteBuffer[kj]= 0;
int r, g, b //Primero la distancia, luego el valor inicial
Punto flotante rStep, gStep, bStep//El tamaño del paso de cada color
//Obtener la diferencia de color
r =(getr value(clrEnd)-getr value(clr inicio));
g =(GetGValue(clrEnd)-GetGValue(clr inicio));
b =(getb valor(clrEnd)-getb valor(clr inicio));
int nSteps = max(abs(r), max(abs(g),ABS(b)));
flotación f paso =(flotación)(85-m _ iFlameHeight)/(float)n pasos;
//Calcular el tamaño del paso de cada color
rStep = r/(float)ns pasos;
gStep = g/(float)ns teps;
bStep = b/(float)ns teps;
//Restablece el color a la posición inicial
r = getr valor(clr inicio);
g = GetGValue(clr inicio);
b = getb valor(clr inicio);
for(int iOnBand = 0; iOnBand & ltnStepsiOnBand++)
{
//COLORREF color = RGB(r+rStep * banda de iones, g + gStep*iOnBand, b+bStep * banda de iones);
COLORREF color = RGB(b+bStep * banda de iones, g + gStep*iOnBand, r+rStep * banda de iones
long lIndex = (int)(banda de iones *); f paso);
m _ pPalletteBuffer[lIndex+(85-m _ iFlameHeight)]= color; //Completa el valor del color
}
}
//Macro para obtener números enteros aleatorios dentro de un rango específico*/Esta es una macro para obtener números aleatorios basados en un rango.
#define getrandom(min,max)((rand()%(int)(((max)+1)-(min))+(min))
# incluir & lttime.h & gt
Rutina Voidcfire::Establecer puntos de acceso()//Establecer los puntos de acceso
{
ClrHotSpots() //Primer borrado; el punto de combustión.
//m_iAvgFlameWidth
long l position = 0; //Acumula según la posición del eje horizontal hasta alcanzar el límite de ancho.
while(l position & lt; m_iWidth)
{
//A ver si debemos hacer una llama
if ( getrandom (0, 100)<m_ifirecharce)//Obtenga un número aleatorio para ver si está dentro del rango de probabilidad de combustión. Si no, omítelo.
{
//Obtener el ancho de la llama
long lflame width = get random(1, m _ iAvgFlameWidth); //Obtener un ancho de llama aleatoriamente.
for(int I = 0; i & ltlFlameWidthi++)
{
if(l position & lt;M_iWidth) //Si la posición está dentro del pantalla, Establecer un punto de ignición.
{
m _ pFireBits[m _ py indexes[m _ ifi resources]+lPosition]= 254;
l posición++;
}
}
}
l posición++;
}
//for(x = 0; x & ltm _ iWidthx++)
// {
// if (getrandom(0, 100) <m_charge)
// {
// }
// }
}
Voidcfiire rutina::hacer líneas()//Generar líneas de escaneo renderizadas.
{
int x, y;
for(x = 0; x & ltm _ iWidthX++) // Bucle horizontal, de izquierda a derecha del pantalla .
{
for(y = m _ ifi recurso; y & ltm _ ih altura-1; Y++) //Circulación longitudinal, desde el foco del fuego hasta la altura de la llama
//for(y = m _ I altura; y & gtm _ iFireSourcey -)
{
//m _ pFireBits[m _ py indexes[y-1 ]+x]= Promedio(x, y);
m _ pFireBits[m _ py indexes[y+1]+x]= Promedio(x, y); valor promedio de la línea de escaneo.
}
}
}
Carbón sin firmar CFireRoutine::Average(int x, int y)
{
Unsigned char ave_color
Unsigned char ave1, ave2, ave3, ave4, ave5, ave6, ave7
//Asegúrate de que no estemos en el último línea... Siempre que no sea la última línea de escaneo, el promedio se calcula de la siguiente manera.
if(y == m_iHeight)
ave 1 = m _ pFireBits[m _ py indexes[y-1]+x]
Otros<; /p>
ave 1 = m _ pFireBits[m _ py indexes[y+1]+x];
//El método de escanear el valor promedio de las líneas, toma un círculo con X e Y como centro, una elipse horizontal con un radio pequeño de 1 y un radio grande de 2, obtenga el color de este rango y luego calcule el promedio:
//Básicamente el estilo de la imagen a continuación: Formato: Tome el número de punto (coordenadas)
/*
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 índices[y] ]+x+2];
ave 6 = m_pFireBits[m_py índices[y]+x-2];
ave 7 = m_pFireBits[m_ py índices[ y]+x];
ave _ color =(ave 1+ave 2+ave 3+ave 4+ave 5+ave 6+ave 7)/7;
/ /Encuentra el color promedio y devuélvelo.
return(ave _ color);
}
//Renderiza según la memoria de vídeo.
void CFireRoutine::Render(DWORD * pvideomememory,
int iwidth,
alto interno
)
{
set hotspots(); //Genera puntos de acceso aleatorios para generar puntos de combustión.
make lines(); //Hacer todos los cálculos matemáticos y actualizaciones de pantalla //Generar líneas de escaneo y actualizar la pantalla.
//Ahora simplemente transfiero los fragmentos a la memoria de video // y hago una copia almacenada en BitBlt de la memoria de video.
Unsigned char * pSrcBitlin//= m _ pFireBits+(m _ I width * 3); // Deshacernos de nuestra fuente de fuego // Obtener la fuente de fuego.
BYTE * dst//=(BYTE *)Dib-& gt;pMemoria de memoria de vídeo;
Byte r;
Byte g;
Byte b;
for(int I = 0;i<m_ih height-3;I++) //Escaneo progresivo
{
dst = (byte* )&pvideomememory[(I width * I)];//Obtener la línea actual del video
pSrcBitlin = &m_pFireBits[m_py indexes[I +3]] //Establecer el puntero de datos de la línea de escaneo;
for(int x = 0; x & ltm _ iWidthx++)
{
//Color de síntesis, tenga en cuenta que el color índice toma el componente RGB, luego agrega profundidad y saturación, y luego las compensa.
r = getr valor(m _ pPalletteBuffer[pSrcBitlin[x]]);
g = GetGValue(m _ pPalletteBuffer[pSrcBitlin[x]]); p>b = getb valor(m _ pPalletteBuffer[pSrcBitlin[x]]);
dst[0]=(BYTE)((r-dst[0])* m _ I alpha+(dst [ 0]<<8))>>8);
dst[1]=(BYTE)(((g-dst[1])* m _ I alfa+(dst[ 1]<<8 ))>>8);
dst[2]=(BYTE)(((b-dst[2])* m _ I alfa+(dst[2 ]& lt;& lt8))& gt;& gt8);
dst+= 4;
}
}
}
En cuanto a En el código fuente de magma y ondas de agua, los conceptos son similares. Primero se establece el modelo de color y luego se hace coincidir con el búfer. Después de una cuidadosa comparación, podemos entenderlos.