想要做这样一个火焰燃烧的效果,才学习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
}
}