MayAcho 2016-07-26 02:57 采纳率: 66.7%
浏览 1760
已结题

WPF做一个火焰燃烧的效果,请求指点

图片说明

想要做这样一个火焰燃烧的效果,才学习C#不久,对这一块不是很了解,希望最终能实现火焰逐步扩散燃烧(以一个点为中心)逐步向四周扩散,并且能比如通过鼠标左键来实现“灭火”的功能,希望大神能指点一二,这是找的火焰效果的源码,求指点该怎么修改!

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Threading;

namespace WPFFireApp
{
    /// <summary>
    /// Adorner that disables all controls that fall under it
    /// </summary>
    public class FireAdorner : Adorner
    {
        private BitmapPalette _pallette = null;
        private const int DPI = 96;
        private FireGenerator _fireGenerator = new FireGenerator(600, 50);

        /// <summary>
        /// Constructor for the adorner
        /// </summary>
        /// <param name="adornerElement">The element to be adorned</param>
        public FireAdorner(UIElement adornerElement)
            : base(adornerElement)
        {           
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);       
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {       
            InvalidateVisual();
        }

        /// <summary>
        /// Called to draw on screen
        /// </summary>
        /// <param name="drawingContext">The drawind context in which we can draw</param>
        protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            // only set the pallette once (dont do in constructor as causes odd errors if exception occurs)
            if (_pallette == null)
                _pallette = SetupFirePalette();

            _fireGenerator.UpdateFire();            

            BitmapSource bs = BitmapSource.Create(_fireGenerator.Width, _fireGenerator.Height, DPI, DPI, 
                PixelFormats.Indexed8, _pallette, _fireGenerator.FireData, _fireGenerator.Width);
            drawingContext.DrawImage(bs, new Rect(0, 0, this.DesiredSize.Width, this.DesiredSize.Height));      
        }

        private BitmapPalette SetupFirePalette()
        {
            List<Color> myList = new List<Color>();

            // seutp the basic array we will modify
            for (int i = 0; i <= 255; i++)
            {
                myList.Add(new Color());
            }

            for (int i = 0; i < 64; i++)
            {               
                Color c1 = new Color();
                c1.R = (byte)(i * 4);
                c1.G = (byte)(0);
                c1.B = (byte)(0);
                c1.A = 255;
                myList[i] = c1;

                Color c2 = new Color();
                c2.R = (byte)(255);
                c2.G = (byte)(i * 4);
                c2.B = (byte)(0);
                c2.A = 255;
                myList[i+64] = c2;

                Color c3 = new Color();
                c3.R = (byte)(255);
                c3.G = (byte)(255);
                c3.B = (byte)(i * 4);
                c3.A = 255;
                myList[i+128] = c3;

                Color c4 = new Color();
                c4.R = (byte)(255);
                c4.G = (byte)(255);
                c4.B = (byte)(255);
                c4.A = 255;
                myList[i + 192] = c4;
            }

            BitmapPalette bp = new BitmapPalette(myList);
            return bp;
        }
    }
}

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;

namespace WPFFireApp
{
    public class FireGenerator
    {
        #region Private Members

        private Random r = new Random();

        private int _width;
        private int _height;
        private byte[] _fireData;

        #endregion

        #region Constructor

        public FireGenerator(int width, int height)
        {
            _width = width;
            _height = height;

            _fireData = new byte[_width * _height];
        }

        #endregion

        public byte[] FireData
        {
            get { return _fireData; }
        }

        public int Height
        {
            get { return _height; }
        }

        public int Width
        {
            get { return _width; }
        }

        #region Private Methods

        private void GenerateBaseline()
        {
            for (int x = 0; x < _width; x++)
            {
                int nBytePos = GetBytePos(x, _height - 1);
                _fireData[nBytePos] = GetRandomNumber();
            }
        }

        public void UpdateFire()
        {
            GenerateBaseline();

            for (int y = 0; y < _height - 1; y++)           
            {
                for (int x = 0; x < _width; x++)
                {
                    int leftVal;

                    if (x == 0)
                        leftVal = _fireData[GetBytePos(_width - 1, y)];
                    else
                        leftVal = _fireData[GetBytePos(x - 1, y)];

                    int rightVal;
                    if (x == _width - 1)
                        rightVal = _fireData[GetBytePos(0, y)];
                    else
                        rightVal = _fireData[GetBytePos(x + 1, y)];

                    int belowVal = _fireData[GetBytePos(x, y + 1)];

                    int sum = leftVal + rightVal + (belowVal * 2);
                    int avg = sum / 4;

                    // auto reduce it so you get lest of the forced fade and more vibrant fire waves
                    if (avg > 0)
                        avg--;

                    if (avg < 0 || avg > 255)
                        throw new Exception("Average color calc is out of range 0-255");

                    _fireData[GetBytePos(x, y)] = (byte)avg;
                }
            }
        }

        private byte GetRandomNumber()
        {
            int randomValue = r.Next(2);
            if (randomValue == 0)
                return (byte)0;
            else if (randomValue == 1)
                return (byte)255;
            else
                throw new Exception("Random returned out of bounds");
        }

        private int GetBytePos(int x, int y)
        {
            return ((y * _width) + x);
        }

        #endregion
    }
}

  • 写回答

1条回答 默认 最新

  • w362335821 2016-07-28 03:38
    关注

    能写出这样效果的就能称的上大神了

    评论

报告相同问题?

悬赏问题

  • ¥15 扩散模型sd.webui使用时报错“Nonetype”
  • ¥15 stm32流水灯+呼吸灯+外部中断按键
  • ¥15 将二维数组,按照假设的规定,如0/1/0 == "4",把对应列位置写成一个字符并打印输出该字符
  • ¥15 NX MCD仿真与博途通讯不了啥情况
  • ¥15 win11家庭中文版安装docker遇到Hyper-V启用失败解决办法整理
  • ¥15 gradio的web端页面格式不对的问题
  • ¥15 求大家看看Nonce如何配置
  • ¥15 Matlab怎么求解含参的二重积分?
  • ¥15 苹果手机突然连不上wifi了?
  • ¥15 cgictest.cgi文件无法访问