v0.1
This commit is contained in:
170
Subsurface/Source/Particles/Particle.cs
Normal file
170
Subsurface/Source/Particles/Particle.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Subsurface.Particles
|
||||
{
|
||||
class Particle
|
||||
{
|
||||
private ParticlePrefab prefab;
|
||||
|
||||
private Vector2 position;
|
||||
private Vector2 prevPosition;
|
||||
|
||||
private Vector2 velocity;
|
||||
|
||||
private float rotation;
|
||||
private float prevRotation;
|
||||
|
||||
private float angularVelocity;
|
||||
|
||||
private Vector2 size;
|
||||
private Vector2 sizeChange;
|
||||
|
||||
private Color color;
|
||||
private float alpha;
|
||||
|
||||
private float lifeTime;
|
||||
|
||||
private Vector2 velocityChange;
|
||||
|
||||
private Vector2 drawPosition;
|
||||
|
||||
private float checkCollisionTimer;
|
||||
|
||||
public bool InWater
|
||||
{
|
||||
get { return prefab.inWater; }
|
||||
}
|
||||
|
||||
public Vector2 yLimits
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Vector2 Size
|
||||
{
|
||||
get { return size; }
|
||||
set { size = value; }
|
||||
}
|
||||
|
||||
public Vector2 VelocityChange
|
||||
{
|
||||
get { return velocityChange; }
|
||||
set { velocityChange = value; }
|
||||
}
|
||||
|
||||
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation)
|
||||
{
|
||||
this.prefab = prefab;
|
||||
|
||||
this.position = position;
|
||||
prevPosition = position;
|
||||
|
||||
drawPosition = ConvertUnits.ToDisplayUnits(position);
|
||||
|
||||
velocity = speed;
|
||||
|
||||
this.rotation = rotation + Rand.Range(prefab.startRotationMin, prefab.startRotationMax);
|
||||
prevRotation = rotation;
|
||||
|
||||
angularVelocity = prefab.angularVelocityMin + (prefab.angularVelocityMax - prefab.angularVelocityMin) * Rand.Range(0.0f, 1.0f);
|
||||
|
||||
lifeTime = prefab.lifeTime;
|
||||
|
||||
size = prefab.startSizeMin + (prefab.startSizeMax - prefab.startSizeMin) * Rand.Range(0.0f, 1.0f);
|
||||
|
||||
sizeChange = prefab.sizeChangeMin + (prefab.sizeChangeMax - prefab.sizeChangeMin) * Rand.Range(0.0f, 1.0f);
|
||||
|
||||
yLimits = Vector2.Zero;
|
||||
|
||||
color = prefab.startColor;
|
||||
alpha = prefab.startAlpha;
|
||||
|
||||
velocityChange = prefab.velocityChange;
|
||||
}
|
||||
|
||||
public bool Update(float deltaTime)
|
||||
{
|
||||
//over 3 times faster than position += velocity * deltatime
|
||||
position.X += velocity.X * deltaTime;
|
||||
position.Y += velocity.Y * deltaTime;
|
||||
|
||||
if (prefab.rotateToDirection)
|
||||
{
|
||||
rotation = MathUtils.VectorToAngle(velocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation += angularVelocity * deltaTime;
|
||||
}
|
||||
|
||||
velocity.X += velocityChange.X * deltaTime;
|
||||
velocity.Y += velocityChange.Y * deltaTime;
|
||||
|
||||
size.X += sizeChange.X * deltaTime;
|
||||
size.Y += sizeChange.Y * deltaTime;
|
||||
|
||||
alpha += prefab.colorChange.W * deltaTime;
|
||||
|
||||
color = new Color(
|
||||
color.R / 255.0f + prefab.colorChange.X * deltaTime,
|
||||
color.G / 255.0f + prefab.colorChange.Y * deltaTime,
|
||||
color.B / 255.0f + prefab.colorChange.Z * deltaTime);
|
||||
|
||||
if (yLimits!=Vector2.Zero)
|
||||
{
|
||||
if (position.Y>yLimits.X || position.Y<yLimits.Y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (prefab.deleteOnHit)
|
||||
{
|
||||
if (checkCollisionTimer > 0.0f)
|
||||
{
|
||||
checkCollisionTimer -= deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Submarine.InsideWall(new Vector2(drawPosition.X, -drawPosition.Y)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
checkCollisionTimer = 0.05f;
|
||||
}
|
||||
}
|
||||
|
||||
lifeTime -= deltaTime;
|
||||
|
||||
if (lifeTime <= 0.0f || alpha <= 0.0f || size.X <= 0.0f || size.Y <= 0.0f) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
drawPosition = Physics.Interpolate(prevPosition, position);
|
||||
drawPosition.Y = -drawPosition.Y;
|
||||
float drawRotation = Physics.Interpolate(prevRotation, rotation);
|
||||
|
||||
drawPosition = ConvertUnits.ToDisplayUnits(drawPosition);
|
||||
|
||||
|
||||
spriteBatch.Draw(
|
||||
prefab.sprite.Texture,
|
||||
drawPosition,
|
||||
null,
|
||||
color*alpha,
|
||||
drawRotation,
|
||||
prefab.sprite.origin,
|
||||
size,
|
||||
SpriteEffects.None, prefab.sprite.Depth);
|
||||
|
||||
prevPosition = position;
|
||||
prevRotation = rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Subsurface/Source/Particles/ParticleManager.cs
Normal file
108
Subsurface/Source/Particles/ParticleManager.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Subsurface.Particles
|
||||
{
|
||||
class ParticleManager
|
||||
{
|
||||
public static int particleCount;
|
||||
|
||||
private const int MaxParticles = 1500;
|
||||
private Particle[] particles;
|
||||
|
||||
private Dictionary<string, ParticlePrefab> prefabs;
|
||||
|
||||
Camera cam;
|
||||
|
||||
public ParticleManager(string configFile, Camera cam)
|
||||
{
|
||||
this.cam = cam;
|
||||
|
||||
particles = new Particle[MaxParticles];
|
||||
|
||||
XDocument doc = ToolBox.TryLoadXml(configFile);
|
||||
if (doc == null) return;
|
||||
|
||||
prefabs = new Dictionary<string, ParticlePrefab>();
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
if (prefabs.ContainsKey(element.Name.ToString()))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + configFile + "! Each particle prefab must have a unique name.");
|
||||
continue;
|
||||
}
|
||||
prefabs.Add(element.Name.ToString(), new ParticlePrefab(element));
|
||||
}
|
||||
}
|
||||
|
||||
public Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed)
|
||||
{
|
||||
return CreateParticle(prefabName, position, new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * speed, angle);
|
||||
}
|
||||
|
||||
public Particle CreateParticle(string prefabName, Vector2 position, Vector2 speed, float rotation=0.0f)
|
||||
{
|
||||
ParticlePrefab prefab;
|
||||
prefabs.TryGetValue(prefabName, out prefab);
|
||||
|
||||
if (prefab==null)
|
||||
{
|
||||
DebugConsole.ThrowError("Particle prefab "+prefabName+" not found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return CreateParticle(prefab, position, speed, rotation);
|
||||
}
|
||||
|
||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation=0.0f)
|
||||
{
|
||||
if (!Submarine.RectContains(cam.WorldView, ConvertUnits.ToDisplayUnits(position))) return null;
|
||||
if (particleCount >= MaxParticles) return null;
|
||||
|
||||
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
||||
|
||||
particles[particleCount].Init(prefab, position, speed, rotation);
|
||||
|
||||
particleCount++;
|
||||
|
||||
return particles[particleCount-1];
|
||||
|
||||
}
|
||||
|
||||
private void RemoveParticle(int index)
|
||||
{
|
||||
particleCount--;
|
||||
|
||||
Particle swap = particles[index];
|
||||
particles[index] = particles[particleCount];
|
||||
particles[particleCount] = swap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
for (int i = 0; i < particleCount; i++)
|
||||
{
|
||||
if (!particles[i].Update(deltaTime)) RemoveParticle(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool inWater)
|
||||
{
|
||||
for (int i = 0; i < particleCount; i++)
|
||||
{
|
||||
if (particles[i].InWater != inWater) continue;
|
||||
|
||||
particles[i].Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
70
Subsurface/Source/Particles/ParticlePrefab.cs
Normal file
70
Subsurface/Source/Particles/ParticlePrefab.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Subsurface.Particles
|
||||
{
|
||||
class ParticlePrefab
|
||||
{
|
||||
public readonly string name;
|
||||
|
||||
public readonly Sprite sprite;
|
||||
|
||||
public readonly float angularVelocityMin, angularVelocityMax;
|
||||
|
||||
public readonly float startRotationMin, startRotationMax;
|
||||
|
||||
public readonly Vector2 startSizeMin, startSizeMax;
|
||||
public readonly Vector2 sizeChangeMin, sizeChangeMax;
|
||||
|
||||
public readonly Color startColor;
|
||||
public readonly float startAlpha;
|
||||
|
||||
public readonly Vector4 colorChange;
|
||||
|
||||
public readonly float lifeTime;
|
||||
|
||||
public readonly bool deleteOnHit;
|
||||
|
||||
public readonly Vector2 velocityChange;
|
||||
|
||||
public readonly bool inWater;
|
||||
|
||||
public readonly bool rotateToDirection;
|
||||
|
||||
public ParticlePrefab(XElement element)
|
||||
{
|
||||
name = element.Name.ToString();
|
||||
|
||||
string spritePath = ToolBox.GetAttributeString(element, "sprite", "");
|
||||
sprite = new Sprite(spritePath, new Vector2(0.5f,0.5f));
|
||||
|
||||
angularVelocityMin = ToolBox.GetAttributeFloat(element, "angularvelocitymin", 0.0f);
|
||||
angularVelocityMax = ToolBox.GetAttributeFloat(element, "angularvelocitymax", 0.0f);
|
||||
|
||||
startSizeMin = ToolBox.GetAttributeVector2(element, "startsizemin", Vector2.One);
|
||||
startSizeMax = ToolBox.GetAttributeVector2(element, "startsizemax", Vector2.One);
|
||||
|
||||
sizeChangeMin = ToolBox.GetAttributeVector2(element, "sizechangemin", Vector2.Zero);
|
||||
sizeChangeMax = ToolBox.GetAttributeVector2(element, "sizechangemax", Vector2.Zero);
|
||||
|
||||
startRotationMin = ToolBox.GetAttributeFloat(element, "startrotationmin", 0.0f);
|
||||
startRotationMax = ToolBox.GetAttributeFloat(element, "startrotationmax", 0.0f);
|
||||
|
||||
startColor = new Color(ToolBox.GetAttributeVector4(element, "startcolor", Vector4.One));
|
||||
startAlpha = ToolBox.GetAttributeFloat(element, "startalpha", 1.0f);
|
||||
|
||||
deleteOnHit = ToolBox.GetAttributeBool(element, "deleteonhit", false);
|
||||
|
||||
colorChange = ToolBox.GetAttributeVector4(element, "colorchange", Vector4.Zero);
|
||||
|
||||
lifeTime = ToolBox.GetAttributeFloat(element, "lifetime", 5.0f);
|
||||
|
||||
velocityChange = ToolBox.GetAttributeVector2(element, "velocitychange", Vector2.Zero);
|
||||
|
||||
rotateToDirection = ToolBox.GetAttributeBool(element, "rotatetodirection", false);
|
||||
|
||||
inWater = ToolBox.GetAttributeBool(element, "inwater", false);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user