/* Sparx * Copyright August Zinsser 2007 * This program is distributed under the terms of the GNU General Public License */ using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace Pina3D.Particles { public class Particle : Emission { protected ParticleSprite mParticleSprite; protected float mWidth; protected float mHeight; protected float mScale; protected Color mColor; // RGBA protected float mRotation; public ParticleSprite ParticleSprite { set { mParticleSprite = value; } get { return mParticleSprite; } } public float Width { set { mWidth = value; } get { return mWidth; } } public float Height { set { mHeight = value; } get { return mHeight; } } public float Rotation { set { mRotation = value; } get { return mRotation; } } public override int ParticleCount { get { return 1; } } public override int EmitterCount { get { return 0; } } /// /// Creates a new particle /// /// Initial absolute position /// Time in seconds before the particle dies /// The name of the image to use from the Particle Sprite sheet /// Width of the sprite in pixels /// Width of the sprite in pixels /// In radians /// Used for book public Particle(Vector3 position, float lifeSpan, string imageName, float width, float height, float initialRotation) : base(imageName, position, false, lifeSpan) { if (imageName == null) mParticleSprite = new ParticleSprite(); else mParticleSprite = new ParticleSprite(imageName); mWidth = width; mHeight = height; mRotation = initialRotation; mVelocity = new Vector3(0, 0, 0); } private Particle() // TODO: Remove this? { } /// /// Returns a new instance exactly like this one /// /// public override Object Clone() { Particle retPa = new Particle(); retPa.mName = mName + "_clone"; retPa.mPosition = new Vector3(mPosition.X, mPosition.Y, mPosition.Z); retPa.mAge = mAge; retPa.mLifeExpectancy = mLifeExpectancy; retPa.mVelocity = new Vector3(mVelocity.X, mVelocity.Y, mVelocity.Z); retPa.mMyModifiers = mMyModifiers; if (mMyForces != null) { retPa.mMyForces = new List(); for (int i = 0; i < mMyForces.Count; i++) retPa.mMyForces.Add((Force)mMyForces[i].Clone()); } retPa.mAlive = mAlive; retPa.mImmortal = mImmortal; retPa.mParticleSprite = mParticleSprite; retPa.mWidth = mWidth; retPa.mHeight = mHeight; retPa.mRotation = mRotation; retPa.mTransform = mTransform; retPa.mRenderScale = mRenderScale; retPa.mRenderRotation = mRenderRotation; return retPa; } /// /// Jiggles the layer depth slightly to help fix z-fighting /// public void DepthJiggle() // TODO: remove all the auto-jiggly stuff { } /// /// Updates this particle's properites /// /// public override void Update() { base.Update(); float dT = Pina.ElapsedSeconds; // Modifiers float[] combinedColor = { 1f, 1f, 1f, 1f }; Modifier modifier; mScale = 1.0f; for (int i = 0; i < mMyModifiers.Count; i++) { modifier = mMyModifiers[i]; // TODO: convert from [0,255] to [0,1] in the Modifier constructor and cut out all the /255 BS Color modColor = modifier.Color(mAge); combinedColor[0] *= (float)modColor.R / 255f; combinedColor[1] *= (float)modColor.G / 255f; combinedColor[2] *= (float)modColor.B / 255f; combinedColor[3] *= (float)modColor.A / 255f; mScale *= modifier.Scale(mAge); mRotation += modifier.AngularVelocity(mAge) * dT; } mColor = new Color( (byte)(combinedColor[0] * 255), (byte)(combinedColor[1] * 255), (byte)(combinedColor[2] * 255), (byte)(combinedColor[3] * 255)); mRotation %= MathHelper.Pi * 2f; if (!mAlive) Pina.RemoveRenderable(this); } /// /// Draws the particle to the backbuffer /// /// public void Render() { // Find screen translation float XTranslate = Sparx.ScreenTranslate.X; float YTranslate = Sparx.ScreenTranslate.Y; // Find the render transformation Vector3 transformedPosition; Vector3.Transform(ref mPosition, ref mTransform, out transformedPosition); transformedPosition.X += XTranslate; transformedPosition.Y += YTranslate; QuadRenderer.RenderOnNextFrame(ref ParticleSprite.SpriteSheet, mParticleSprite.UVUpperLeft, mParticleSprite.UVLowerRight, transformedPosition, mWidth * mScale * mRenderScale, mHeight * mScale * mRenderScale, mRotation + mRenderRotation, mColor); } } }