/* 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);
}
}
}