我写的那个经典的火焰算法的C++类,欢迎批评!
// Fire.h: interface for the CFire class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FIRE_H__0029C0C9_6ACF_43BA_8F6D_51B74810ABF8__INCLUDED_)
#define AFX_FIRE_H__0029C0C9_6ACF_43BA_8F6D_51B74810ABF8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CFirePlant
{
public:
unsigned char peRed;
unsigned char peGreen;
unsigned char peBlue;
};
class CFire
{
public:
BOOL DrawToDC();
BOOL StartFire();
BOOL SetFireScreen(int,int);
void Play();
CFire(CDC* pDC=NULL);
virtual ~CFire();
private:
BOOL _Play;
BYTE *m_pBuffers;
BYTE *m_pWords;
BOOL flag;
CDC* m_pDC;
void CreateBitmap();
int FireHeight;
int FireWidth;
public:
void FreeMem();
CBitmap m_pBitmap;
CFirePlant mypal[255];
};
#endif // !defined(AFX_FIRE_H__0029C0C9_6ACF_43BA_8F6D_51B74810ABF8__INCLUDED_)
// Fire.cpp: implementation of the CFire class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CFireShow.h"
#include "Fire.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFire::CFire(CDC* pDC/*=NULL*/)
{
m_pDC = pDC ;
FireHeight = FireWidth = 0 ;
m_pWords = NULL ;
m_pBuffers = NULL ;
_Play = FALSE ;
if ( pDC == NULL )
flag = FALSE ;
else
flag = TRUE ;
if ( flag )
{
int index = 0;
for (index=65;index<200;index++)
{
mypal[index].peRed = index+60;
mypal[index].peGreen = index+30;
mypal[index].peBlue = rand()%10;
}/*
for (index = 1; index < 35; index++)
{
mypal[index].peRed = index+25;
mypal[index].peGreen = rand()%10;
mypal[index].peBlue = rand()%10;
}*/
for (index = 0; index < 40; index++)
{
mypal[index].peRed = 0;
mypal[index].peGreen = 0;
mypal[index].peBlue = 0;
}
for (index = 40; index < 45; index++)
{
mypal[index].peRed = index;
mypal[index].peGreen = index-35;
mypal[index].peBlue = rand()%5;
}
for (index = 45; index < 65; index++)
{
mypal[index].peRed = index+75;
mypal[index].peGreen = index;
mypal[index].peBlue = rand()%5;
}
for(index = 200; index < 255; index++)
{
mypal[index].peRed = index;
mypal[index].peGreen = index-rand()%25;
mypal[index].peBlue = rand()%5;
}
mypal[0].peRed = 0;
mypal[0].peGreen = 0;
mypal[0].peBlue = 0;
}
}
CFire::~CFire()
{
}
BOOL CFire::SetFireScreen(int width,int height)
{
if ( width < 10 )
width = 10;
if ( height <10 )
height = 10;
if ( !flag )
return FALSE;
FireHeight = height ;
FireWidth = width ;
m_pWords = new BYTE[height * ( width * 3)];
m_pBuffers = new BYTE[height * width];
if ( m_pWords == NULL || m_pBuffers == NULL )
{
MessageBox(NULL,"矩形堆初始化失败","警告",MB_OK);
return FALSE;
}
CreateBitmap();
return TRUE;
}
void CFire::CreateBitmap()
{
LPBITMAPINFO lpbi;
lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbi->bmiHeader.biWidth = FireWidth;
lpbi->bmiHeader.biHeight = FireHeight;
lpbi->bmiHeader.biPlanes = 1;
lpbi->bmiHeader.biBitCount = 24;
lpbi->bmiHeader.biCompression = BI_RGB;
lpbi->bmiHeader.biSizeImage = 0;
lpbi->bmiHeader.biXPelsPerMeter = 0;
lpbi->bmiHeader.biYPelsPerMeter = 0;
lpbi->bmiHeader.biClrUsed = 0;
lpbi->bmiHeader.biClrImportant = 0;
HBITMAP hBitmap = CreateDIBSection( m_pDC->m_hDC , lpbi, (UINT)DIB_RGB_COLORS, (void **)&m_pWords, NULL, 0 );
delete [] (BYTE *)lpbi;
ASSERT(hBitmap != NULL);
m_pBitmap.Attach( hBitmap ) ;
}
BOOL CFire::StartFire()
{
if ( !flag )
return FALSE ;
{
for(int x = 0; x < FireWidth; x+=(rand()%3))
{
if( rand()%2 )
m_pBuffers[( ( FireHeight - 1 ) * FireWidth ) + x] = 255 ;
else
m_pBuffers[( ( FireHeight - 1 ) * FireWidth ) + x] = 0 ;
}
}
_Play = TRUE ;
return _Play ;
}
BOOL CFire::DrawToDC()
{
if ( !_Play )
return FALSE;
for( int x = ( FireWidth * FireHeight - 1 ); x >= 0; x--)
{
int temp = m_pBuffers[(FireWidth * FireHeight - 1 - x)];
m_pWords[3*x+2] = mypal[temp].peRed;
m_pWords[3*x+1] = mypal[temp].peGreen;
m_pWords[3*x] = mypal[temp].peBlue;
}
return StartFire();
}
void CFire::Play()
{
for( int y = 1; y < FireHeight; y++)
{
for( int x = 1; x < FireWidth; x++)
{
int xy = ( y * FireWidth ) + x;
int xyvalue;
xyvalue = ( m_pBuffers[xy + 1] + m_pBuffers[xy - 1]
+ m_pBuffers[xy + FireWidth] + m_pBuffers[xy - FireWidth]
+ m_pBuffers[xy + FireWidth + 1]
+ m_pBuffers[xy + FireWidth - 1]
+ m_pBuffers[xy - FireWidth + 1]
+ m_pBuffers[xy - FireWidth - 1] ) / 8;
if ( xyvalue != 0 )
{
xyvalue--;
m_pBuffers[xy - FireWidth] = xyvalue;
}
}
}
}
void CFire::FreeMem()
{
if ( flag )
{
if ( m_pBuffers != NULL)
delete m_pBuffers;
m_pDC = NULL;
flag = _Play = FALSE;
}
}
dlg类代码
// CFireShowDlg.cpp : implementation file
//
#include "stdafx.h"
#include "CFireShow.h"
#include "CFireShowDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCFireShowDlg dialog
CCFireShowDlg::CCFireShowDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCFireShowDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCFireShowDlg)
//}}AFX_DATA_INIT
m_pFire = NULL;
}
void CCFireShowDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCFireShowDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCFireShowDlg, CDialog)
//{{AFX_MSG_MAP(CCFireShowDlg)
ON_WM_PAINT()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCFireShowDlg message handlers
BOOL CCFireShowDlg::OnInitDialog()
{
CDialog::OnInitDialog();
GetClientRect(rect);
MemDC = new CDC;
MemDC->CreateCompatibleDC(NULL);
m_pFire = new CFire(MemDC);
if ( m_pFire->SetFireScreen(320,103) )
{
if ( m_pFire->StartFire() )
SetTimer(1,10,NULL);
}
return TRUE;
}
void CCFireShowDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if ( m_pFire->DrawToDC() )
{
MemDC->SelectObject(&(m_pFire->m_pBitmap));
MemDC->SetBkMode(0);
CRect rect(0,85,320,100);
MemDC->SetTextColor(RGB(0,0,0));
MemDC->DrawText("Gemini",rect,DT_RIGHT);
dc.BitBlt( 0, 0, 320,103, MemDC, 0, 0, SRCCOPY );
m_pFire->Play();
}
CDialog::OnPaint();
}
void CCFireShowDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
InvalidateRect(rect,FALSE);
CDialog::OnTimer(nIDEvent);
}
BOOL CCFireShowDlg::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
KillTimer(1);
m_pFire->FreeMem();
delete(MemDC);
delete(m_pFire);
return CDialog::DestroyWindow();
}
感觉我写的CFire类的FreeFire函数总感觉有点不舒服,但写成别的形式都抱撮,哥哥姐姐叔叔阿姨,帮忙看看,对了,这个的效率很高采用24位真彩色显示,可以在 塞样800HZ 128SDR WINXP上支持到1毫秒一次刷新的速度,速度应该可以了吧?