⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 particleeffects.cs

📁 Beginning C# Game Programming 的源代码
💻 CS
字号:
using System;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;
public class ParticleEffects {
	public struct PointVertex {
		public Vector3 v;
		public int color;
		public static readonly VertexFormats Format =   VertexFormats.Position | VertexFormats.Diffuse;
	};

	/// <summary>
	/// Global data for the particles
	/// </summary>
	public struct Particle {
		public Vector3 positionVector;       // Current position
		public Vector3 velocityVector;       // Current velocity
		public Vector3 initialPosition;      // Initial position
		public Vector3 initialVelocity;      // Initial velocity
		public float creationTime;     // Time of creation
		public System.Drawing.Color diffuseColor; // Initial diffuse color
		public System.Drawing.Color fadeColor;    // Faded diffuse color
		public float fadeProgression;      // Fade progression
	};


	private float time = 0.0f;
	private const int bufferChunkSize = 8192; 
	private const int maxBufferSize = bufferChunkSize*4; //supports 4 bufferChunkSize buffers before discarding
	private int baseParticle = maxBufferSize;
	private int particles = 0;
	private const int particlesLimit = 2048;
	private Vector3 location;
	private Vector3 offset;
	private System.Collections.ArrayList particlesList = new System.Collections.ArrayList();
	private System.Collections.ArrayList freeParticles = new System.Collections.ArrayList();
	private System.Random rand = new System.Random();
	public Vector3 EmitterLocation {get { return location; } }
	public Vector3 EmitterOffset { get { return offset; } set { offset = value; } }
	// Geometry
	private VertexBuffer vertexBuffer = null;
	private Texture particleTexture;
	public Texture ParticleTexture { set { particleTexture = value; } }
	private Device device = null;

	/// <summary>
	/// VaporTrail constructor
	/// </summary>
	public ParticleEffects(Device device) {
		this.device = device;
		if (device != null) {
			device.DeviceLost += new System.EventHandler(this.InvalidateDeviceObjects);
			device.Disposing += new System.EventHandler(this.InvalidateDeviceObjects);
			device.DeviceReset += new System.EventHandler(this.RestoreDeviceObjects);
		}
		RestoreDeviceObjects(device, null);
	}
        
	public void InvalidateDeviceObjects(object sender, EventArgs e) {
		if (vertexBuffer != null)
			vertexBuffer.Dispose();
		vertexBuffer = null;
	}
        
	/// <summary>
	/// Restores the device objects
	/// </summary>
	public void RestoreDeviceObjects(object sender, EventArgs e) {
		Device device = (Device)sender;
		// Create a vertex buffer for the particle system.  The size of this buffer
		// does not relate to the number of particles that exist.  Rather, the
		// buffer is used as a communication channel with the device.. we fill in 
		// a bit, and tell the device to draw.  While the device is drawing, we
		// fill in the next bit using NOOVERWRITE.  We continue doing this until 
		// we run out of vertex buffer space, and are forced to discard the buffer
		// and start over at the beginning.
		vertexBuffer = new VertexBuffer(typeof(PointVertex), maxBufferSize, device,  Usage.Dynamic | Usage.WriteOnly | Usage.Points, PointVertex.Format, Pool.Default);
	}
          
	/// <summary>
	/// Updates the thrust effects (vapor trail)
	/// </summary>
	public void UpdateThrustEffect(float ElapsedTime, int NumParticlesToEmit,
		System.Drawing.Color EmitColor,System.Drawing.Color FadeColor, Vector3 Position) {
		time += ElapsedTime;
		location = Position;
		for (int i = particlesList.Count-1; i >= 0; i--) {
			Particle p = (Particle)particlesList[i];
			// Calculate new position
			float fT = time - p.creationTime;
			p.fadeProgression -= ElapsedTime * 0.60f;
			p.positionVector   = p.initialVelocity * fT + p.initialPosition;
			p.velocityVector.Z = 0;
			if (p.fadeProgression < 0.0f)
				p.fadeProgression = 0.0f;
			// Kill old particles
			if (p.fadeProgression <= 0.0f) {
				// Kill particle
				freeParticles.Add(p);
				particlesList.RemoveAt(i);
				particles--;
			}
			else
				particlesList[i] = p;
		}
		// Emit new particles
		int particlesEmit = particles + NumParticlesToEmit;
		while(particles < particlesLimit && particles < particlesEmit) {
			Particle particle;
			if (freeParticles.Count > 0) {
				particle = (Particle)freeParticles[0];
				freeParticles.RemoveAt(0);
			}
			else {
				particle = new Particle();
			}
			// Emit new particle
			particle.initialPosition = Position + offset;
			particle.positionVector = particle.initialPosition;
			particle.velocityVector = particle.initialVelocity;
			particle.diffuseColor = EmitColor;
			particle.fadeColor    = FadeColor;
			particle.fadeProgression      = 1.0f;
			particle.creationTime     = time;
			particlesList.Add(particle);
			particles++;
		}
	}

	/// <summary>
	/// Renders the scene
	/// </summary>
	public void Render() {
		// Set the render states for using point sprites
		device.RenderState.ZBufferWriteEnable = false;
		device.RenderState.AlphaBlendEnable = true;
		device.RenderState.SourceBlend = Blend.One;
		device.RenderState.DestinationBlend = Blend.One;
		bool lightEnabled = device.RenderState.Lighting;
		device.RenderState.Lighting = false;
		device.SetTexture(0, particleTexture);
		device.Transform.World = Matrix.Identity;
		device.RenderState.PointSpriteEnable = true;
		device.RenderState.PointScaleEnable = true;
		device.RenderState.PointSize = 1.0f;
		device.RenderState.PointScaleA = 0f;
		device.RenderState.PointScaleB = 1.0f;
		device.RenderState.PointScaleC = 1.0f;
		// Set up the vertex buffer to be rendered
		device.SetStreamSource(0, vertexBuffer, 0);
		device.VertexFormat = PointVertex.Format;
		PointVertex[] vertices = null;
		int numParticlesToRender = 0;
		// Lock the vertex buffer.  We fill the vertex buffer in small
		// chunks, using LockFlags.NoOverWrite.  When we are done filling
		// each chunk, we call DrawPrim, and lock the next chunk.  When
		// we run out of space in the vertex buffer, we start over at
		// the beginning, using LockFlags.Discard.
		baseParticle += bufferChunkSize;
		if (baseParticle >= maxBufferSize)
			baseParticle = 0;
		int count = 0;
		vertices = (PointVertex[])vertexBuffer.Lock(baseParticle * DXHelp.GetTypeSize(typeof(PointVertex)), typeof(PointVertex), (baseParticle != 0) ? LockFlags.NoOverwrite : LockFlags.Discard, bufferChunkSize);
		foreach(Particle p in particlesList) {
			Vector3 vPos = p.positionVector;
			Vector3 velocityVector = p.velocityVector;
			float LengthSq = velocityVector.LengthSq();
			uint steps;
			if (LengthSq < 1.0f)        steps = 2;
			else if (LengthSq <  4.00f) steps = 3;
			else if (LengthSq <  9.00f) steps = 4;
			else if (LengthSq < 12.25f) steps = 5;
			else if (LengthSq < 16.00f) steps = 6;
			else if (LengthSq < 20.25f) steps = 7;
			else                          steps = 8;
			velocityVector *= -0.01f / (float)steps;
			System.Drawing.Color diffuse = ColorOperator.Lerp(p.fadeColor, p.diffuseColor, p.fadeProgression);
			// Render each particle a bunch of times to get a blurring effect
			for (int i = 0; i < steps; i++) {
				vertices[count].v     = vPos;
				vertices[count].color = diffuse.ToArgb();
				count++;
				if (++numParticlesToRender == bufferChunkSize) {
					// Done filling this chunk of the vertex buffer.  Lets unlock and
					// draw this portion so we can begin filling the next chunk.
					vertexBuffer.Unlock();
					device.DrawPrimitives(PrimitiveType.PointList, baseParticle, numParticlesToRender);
					// Lock the next chunk of the vertex buffer.  If we are at the 
					// end of the vertex buffer, LockFlags.Discard the vertex buffer and start
					// at the beginning.  Otherwise, specify LockFlags.NoOverWrite, so we can
					// continue filling the VB while the previous chunk is drawing.
					baseParticle += bufferChunkSize;
					if (baseParticle >= maxBufferSize)
						baseParticle = 0;
					vertices = (PointVertex[])vertexBuffer.Lock(baseParticle * DXHelp.GetTypeSize(typeof(PointVertex)), typeof(PointVertex), (baseParticle != 0) ? LockFlags.NoOverwrite : LockFlags.Discard, bufferChunkSize);
					count = 0;
					numParticlesToRender = 0;
				}
				vPos += velocityVector;
			}
		}

		// Unlock the vertex buffer
		vertexBuffer.Unlock();
		// Render any remaining particles
		if (numParticlesToRender > 0)
			device.DrawPrimitives(PrimitiveType.PointList, baseParticle, numParticlesToRender);
		// Reset render states
		device.RenderState.PointSpriteEnable = false;
		device.RenderState.PointScaleEnable = false;
		device.RenderState.Lighting = lightEnabled;
		device.RenderState.ZBufferWriteEnable = true;
		device.RenderState.AlphaBlendEnable = false;
	}

	public void Dispose() {
		if (vertexBuffer != null)
			vertexBuffer.Dispose();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -