微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 硬件电路设计 > 电子工程师杂谈 > 动态火焰模拟c程序,按要求修改及解释

动态火焰模拟c程序,按要求修改及解释

时间:10-02 整理:3721RD 点击:
//改渐变为单色火焰,改单像素点为多个像素点组成的大像素点
#include <graphics.h>
#include <conio.h>
#include <time.h>
// 宏常量
#define        WIDTH                640
#define HEIGHT                480
#define FIREWIDTH        480//320
#define        FIREHEIGHT        300//180
// 全局变量
COLORREF        g_Colors[193];                                                // 火焰色系中使用的全部颜色193?
BYTE                g_Fire[FIREWIDTH];                                        // 火焰数据
BYTE                g_Bits[FIREHEIGHT * FIREWIDTH];                // 火焰数据
// 火焰属性
int m_nDecay = 3;                        // 衰减度,范围 [1, 100],默认 5
int m_nFlammability = 385;        // 易燃性,范围 [1, 399],默认 385
int m_nMaxHeat = 192;                // 最高热度,范围 [0, 192],默认 192
int m_nSpreadRate = 1;                // 传播速率,范围 [1, 100],默认 20
int m_nSize = 450;                        // 火源宽度,范围 [40, FIREWIDTH],默认 160
int m_nSmoothness = 1;                // 平滑度,范围 [0, 5],默认 1
int m_nDistribution =10;        // 分布,范围 [0, 10],默认 1
int m_nChaos = 50;                        // 混沌,范围 [1, 100],默认 50

// 初始化火焰
void InitFire()
{
        // 初始化颜色
        int r, g, b;
        // 默认红色火焰。根据注释选择不同的火焰效果
      b = 256+256+255;        g = 256+255;        r = 255;        // 红色火焰
     // r = 256+256+255;        g = 256+255;        b = 255;        // 蓝色火焰
         // g = 256+256+255;        b = 256+255;        r = 255;        // 绿色火焰
        // 生成火焰色系
        for(int i = 192; i >= 0; i--)
        {
                g_Colors[i] = RGB((r > 255) ? 255 : r, (g > 255) ? 255 : g, (b > 255) ? 255 : b);
                //g_Colors[i] = RGB( 255, 0, 0);//自己修改的,但是却是蓝色,为什么呢,不应该是红色么?
            r = (r > 3) ? (r - 4) : 0;
                g = (g > 3) ? (g - 4) : 0;
                b = (b > 3) ? (b - 4) : 0;
               
            
       
        }
        // 置空火焰数组
        memset(g_Fire, 0, FIREWIDTH);
        memset(g_Bits, 0, FIREWIDTH * FIREHEIGHT);
}

// 画色系(不重要,可去,已屏蔽)
//void DrawColorScheme()
//{
//        POINT s[8] = {        {0,        450}, {580, 450}, {580, 420}, {610, 420},
//                                        {610, 0}, {639, 0},          {639, 479}, {0, 479}        };
//        HRGN rgn1 = CreatePolygonRgn(s, 8, WINDING);
//        HRGN rgn2 = CreateEllipticRgn(550, 390, 611, 451);
//        CombineRgn(rgn1, rgn1, rgn2, RGN_DIFF);
        // 定义裁剪区域
        //setcliprgn(rgn1);                        // 设置区域 rgn 为裁剪区
        //DeleteObject(rgn1);
        //DeleteObject(rgn2);
        // 剪裁区画色系
        //int c, x, y;
        //for (int i = 0; i < 1120; i++)
        //{
        //        c = int(i / 5.8);
        //        x = (i <= 479 ? 639 : 639 - i + 479);
        //        y = (i <= 479 ? i : 479);
        //        setcolor(BGR(g_Colors[c]));
        //        line(0, 0, x, y);
//        }
        // 取消裁剪区域
//        setcliprgn(NULL);
//}

// 计算火焰的每个点(这里不懂,(rand() & 1如何?究竟怎么实现的,怎么理解)
inline void BurnPoint(BYTE* pRow, BYTE* pNextRow)
{
        BYTE* pTarget;
        int off = rand() % (m_nDistribution + 1);//分布0-10,m_nDistribution=1,off是0-1随机数
        int val = m_nDecay + 1;//m_nDecay衰减度+1即5+1=6
        val = rand() % val;//产生0-5的随机数
        val = *pNextRow - val;
        pTarget = (rand() & 1) ? pRow + off : pRow - off;
        *pTarget = (val > 0) ? (BYTE)val : 0;
}

// 计算火焰
void RenderFlame()
{
        int xStart, xEnd, x, y;
        BYTE* pRow;
        BYTE* pNextRow;
        xStart = (FIREWIDTH - m_nSize) / 2;//x轴起火点(480-火源宽度160)/2
        xEnd = xStart + m_nSize +1;//结束点10+160+1
        pRow = g_Bits;//火焰数据?
        for (x = 0; x < FIREWIDTH; x++)
        {
                if (x < (xStart + m_nDistribution) || x >= (xEnd - m_nDistribution))//m_nDistribution分布=1
                        g_Fire[x] = 0;//        g_Fire[FIREWIDTH]
                *pRow++ = g_Fire[x];//火焰边缘修改
        }
        for (y = FIREHEIGHT - 1; y > 0; y--)        // y = 0 火焰最大;y++ 火焰变小
        {
                pRow = (g_Bits + FIREWIDTH * y);
                pNextRow = (g_Bits + FIREWIDTH * (y - 1));
                if (rand() & 1)
                {
                        for (x = 0; x < FIREWIDTH; x++)
                        {
                                BurnPoint(pRow, pNextRow);
                                pRow++;
                                pNextRow++;
                        }
                }
                else
                {
                        pRow += FIREWIDTH - 1;
                        pNextRow += FIREWIDTH - 1;
                        for (x = 0; x < FIREWIDTH; x++)
                        {
                                BurnPoint(pRow, pNextRow);
                                pRow--;
                                pNextRow--;
                        }
                }
        }
        if (rand() % (400 - m_nFlammability) == 0)//400-易燃性385=15,即0-14随机数
        {
                int off = m_nSize - 5;//火源宽度-5=160-5=155
                off = rand() % off;//即0-154随机数
                off += xStart;
                for (x = off; x < off + 5; x++)
                        g_Fire[x] = 239;//239?
        }
        for (x = xStart; x < xEnd; x++)
        {
                if (g_Fire[x] < m_nMaxHeat)//最高热度
                {
                        int val = rand() % m_nChaos + 1;//浑沌50?+1即产生0-50随机数
                        val -= m_nChaos / 2;
                        val += m_nSpreadRate;
                        val += g_Fire[x];//val=val-25+传播速度20+g_Fire[x]
                        if ( val > m_nMaxHeat)
                                g_Fire[x] = m_nMaxHeat;
                        else if (val < 0)
                                g_Fire[x] = 0;
                        else
                                g_Fire[x] = val;
                }
                else
                        g_Fire[x] = m_nMaxHeat;
        }
        if (m_nSmoothness > 0)//平滑度?
        {
                xStart += m_nSmoothness;
                xEnd -= m_nSmoothness;
                for (x = xStart; x < xEnd; x++)
                {
                        int val = 0;
                        for (y = x - m_nSmoothness; y < x + 1 + m_nSmoothness; y++)
                                val += g_Fire[y];
                        g_Fire[x] = val / (2 * m_nSmoothness + 1);
                }
        }
}

// 显示火焰
void PaintFlame(int offset_x, int offset_y)
{
        DWORD* pDst = GetImageBuffer();        // 获取显存指针
        for(int y = 0; y < FIREHEIGHT; y++)
                for(int x = 0; x < FIREWIDTH; x++)
                {
                        COLORREF c = g_Colors[g_Bits[y * FIREWIDTH + x]];//如何设置大一点的像素点
                        pDst[(offset_y - y) * WIDTH + offset_x + x] = c;
                }
        FlushBatchDraw();                                // 使显存操作生效
}

// 主函数
void main()
{
        initgraph(WIDTH, HEIGHT);                // 创建绘图窗口
        srand((unsigned)time(NULL));        // 设置随机种子
        InitFire();                                                // 初始化火焰
//        DrawColorScheme();                                // 绘制色系图
        while(!kbhit())                                        // 按任意键退出
        {
                RenderFlame();                                // 渲染火焰
                PaintFlame(145, 320);                // 显示火焰145,320
                Sleep(33);                                        // 延时
        }
        closegraph();
}

请大家看看哦,交流交流,不太理解呢

COLORREF        g_Colors[193]这句是设置一堆颜色变量么?那我修改g_Colors[i] = RGB( 255, 0, 0)不应该全是红色么?却是蓝色。g_Colors[i] = RGB( 255, 255, 0)把却是补了矩形框的颜色

由于想要模拟在led显示屏上的效果,所以想把单像素点变大,如何变呢,我不是怎么懂计算火焰每个点那里,我觉得应该在那里改,却不知道如何下手,或许也可以加渲染效果,用一排排小圆渲染,那有怎么办呢?

走过路过交流交流啦,改完之后回馈大家一起学习啦

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top