Particle additions:
- Support for subemitters (= particles can emit particles). - Option to set a different velocity change value for particles in water (can be used to simulate buouancy). - Fixed drag vector & timer not being reset when initializing a particle.
This commit is contained in:
@@ -293,6 +293,7 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
ParticleManager = new ParticleManager("Content/Particles/ParticlePrefabs.xml", GameScreen.Cam);
|
ParticleManager = new ParticleManager("Content/Particles/ParticlePrefabs.xml", GameScreen.Cam);
|
||||||
|
ParticleManager.LoadPrefabs();
|
||||||
DecalManager = new DecalManager("Content/Particles/DecalPrefabs.xml");
|
DecalManager = new DecalManager("Content/Particles/DecalPrefabs.xml");
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ namespace Barotrauma.Particles
|
|||||||
private float lifeTime;
|
private float lifeTime;
|
||||||
|
|
||||||
private Vector2 velocityChange;
|
private Vector2 velocityChange;
|
||||||
|
private Vector2 velocityChangeWater;
|
||||||
|
|
||||||
private Vector2 drawPosition;
|
private Vector2 drawPosition;
|
||||||
private float drawRotation;
|
private float drawRotation;
|
||||||
@@ -46,6 +47,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
private List<Gap> hullGaps;
|
private List<Gap> hullGaps;
|
||||||
|
|
||||||
|
private List<ParticleEmitter> subEmitters = new List<ParticleEmitter>();
|
||||||
|
|
||||||
private float animState;
|
private float animState;
|
||||||
private int animFrame;
|
private int animFrame;
|
||||||
|
|
||||||
@@ -71,6 +74,12 @@ namespace Barotrauma.Particles
|
|||||||
set { velocityChange = value; }
|
set { velocityChange = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 VelocityChangeWater
|
||||||
|
{
|
||||||
|
get { return velocityChangeWater; }
|
||||||
|
set { velocityChangeWater = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2 Velocity
|
public Vector2 Velocity
|
||||||
{
|
{
|
||||||
get { return velocity; }
|
get { return velocity; }
|
||||||
@@ -90,6 +99,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
animState = 0;
|
animState = 0;
|
||||||
animFrame = 0;
|
animFrame = 0;
|
||||||
|
dragWait = 0;
|
||||||
|
dragVec = Vector2.Zero;
|
||||||
|
|
||||||
currentHull = Hull.FindHull(position, hullGuess);
|
currentHull = Hull.FindHull(position, hullGuess);
|
||||||
|
|
||||||
@@ -121,9 +132,16 @@ namespace Barotrauma.Particles
|
|||||||
alpha = prefab.StartAlpha;
|
alpha = prefab.StartAlpha;
|
||||||
|
|
||||||
velocityChange = prefab.VelocityChangeDisplay;
|
velocityChange = prefab.VelocityChangeDisplay;
|
||||||
|
velocityChangeWater = prefab.VelocityChangeWaterDisplay;
|
||||||
|
|
||||||
OnChangeHull = null;
|
OnChangeHull = null;
|
||||||
|
|
||||||
|
subEmitters.Clear();
|
||||||
|
foreach (ParticleEmitterPrefab emitterPrefab in prefab.SubEmitters)
|
||||||
|
{
|
||||||
|
subEmitters.Add(new ParticleEmitter(emitterPrefab));
|
||||||
|
}
|
||||||
|
|
||||||
if (prefab.DeleteOnCollision || prefab.CollidesWithWalls)
|
if (prefab.DeleteOnCollision || prefab.CollidesWithWalls)
|
||||||
{
|
{
|
||||||
hullGaps = currentHull == null ? new List<Gap>() : currentHull.ConnectedGaps;
|
hullGaps = currentHull == null ? new List<Gap>() : currentHull.ConnectedGaps;
|
||||||
@@ -158,19 +176,26 @@ namespace Barotrauma.Particles
|
|||||||
rotation += angularVelocity * deltaTime;
|
rotation += angularVelocity * deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefab.WaterDrag > 0.0f &&
|
bool inWater = (currentHull == null || (currentHull.Submarine != null && position.Y - currentHull.Submarine.DrawPosition.Y < currentHull.Surface));
|
||||||
(currentHull == null || (currentHull.Submarine != null && position.Y - currentHull.Submarine.DrawPosition.Y < currentHull.Surface)))
|
if (inWater)
|
||||||
{
|
{
|
||||||
ApplyDrag(prefab.WaterDrag, deltaTime);
|
velocity.X += velocityChangeWater.X * deltaTime;
|
||||||
|
velocity.Y += velocityChangeWater.Y * deltaTime;
|
||||||
|
if (prefab.WaterDrag > 0.0f)
|
||||||
|
{
|
||||||
|
ApplyDrag(prefab.WaterDrag, deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (prefab.Drag > 0.0f)
|
else
|
||||||
{
|
{
|
||||||
ApplyDrag(prefab.Drag, deltaTime);
|
velocity.X += velocityChange.X * deltaTime;
|
||||||
|
velocity.Y += velocityChange.Y * deltaTime;
|
||||||
|
if (prefab.Drag > 0.0f)
|
||||||
|
{
|
||||||
|
ApplyDrag(prefab.Drag, deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
velocity.X += velocityChange.X * deltaTime;
|
|
||||||
velocity.Y += velocityChange.Y * deltaTime;
|
|
||||||
|
|
||||||
size.X += sizeChange.X * deltaTime;
|
size.X += sizeChange.X * deltaTime;
|
||||||
size.Y += sizeChange.Y * deltaTime;
|
size.Y += sizeChange.Y * deltaTime;
|
||||||
|
|
||||||
@@ -191,6 +216,11 @@ namespace Barotrauma.Particles
|
|||||||
lifeTime -= deltaTime;
|
lifeTime -= deltaTime;
|
||||||
if (lifeTime <= 0.0f || alpha <= 0.0f || size.X <= 0.0f || size.Y <= 0.0f) return false;
|
if (lifeTime <= 0.0f || alpha <= 0.0f || size.X <= 0.0f || size.Y <= 0.0f) return false;
|
||||||
|
|
||||||
|
foreach (ParticleEmitter emitter in subEmitters)
|
||||||
|
{
|
||||||
|
emitter.Emit(deltaTime, position, currentHull);
|
||||||
|
}
|
||||||
|
|
||||||
if (!prefab.DeleteOnCollision && !prefab.CollidesWithWalls) return true;
|
if (!prefab.DeleteOnCollision && !prefab.CollidesWithWalls) return true;
|
||||||
|
|
||||||
if (currentHull == null)
|
if (currentHull == null)
|
||||||
@@ -201,7 +231,6 @@ namespace Barotrauma.Particles
|
|||||||
if (prefab.DeleteOnCollision) return false;
|
if (prefab.DeleteOnCollision) return false;
|
||||||
OnWallCollisionOutside(collidedHull);
|
OnWallCollisionOutside(collidedHull);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -281,8 +310,11 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
if (Math.Abs(velocity.X) < 0.0001f && Math.Abs(velocity.Y) < 0.0001f) return;
|
if (Math.Abs(velocity.X) < 0.0001f && Math.Abs(velocity.Y) < 0.0001f) return;
|
||||||
|
|
||||||
|
//TODO: some better way to handle particle drag
|
||||||
|
//this doesn't work that well because the drag vector is only updated every 0.5 seconds, allowing the particle to accelerate way more than it should
|
||||||
|
//(e.g. a falling particle can freely accelerate for 0.5 seconds before the drag takes effect)
|
||||||
dragWait--;
|
dragWait--;
|
||||||
if (dragWait<=0)
|
if (dragWait <= 0)
|
||||||
{
|
{
|
||||||
dragWait = 30;
|
dragWait = 30;
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,11 @@ namespace Barotrauma.Particles
|
|||||||
this.cam = cam;
|
this.cam = cam;
|
||||||
|
|
||||||
particles = new Particle[MaxParticles];
|
particles = new Particle[MaxParticles];
|
||||||
|
|
||||||
LoadPrefabs(configFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadPrefabs(string file)
|
public void LoadPrefabs()
|
||||||
{
|
{
|
||||||
XDocument doc = XMLExtensions.TryLoadXml(file);
|
XDocument doc = XMLExtensions.TryLoadXml(ConfigFile);
|
||||||
if (doc == null || doc.Root == null) return;
|
if (doc == null || doc.Root == null) return;
|
||||||
|
|
||||||
prefabs = new Dictionary<string, ParticlePrefab>();
|
prefabs = new Dictionary<string, ParticlePrefab>();
|
||||||
@@ -47,7 +45,7 @@ namespace Barotrauma.Particles
|
|||||||
{
|
{
|
||||||
if (prefabs.ContainsKey(element.Name.ToString()))
|
if (prefabs.ContainsKey(element.Name.ToString()))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Error in " + file + "! Each particle prefab must have a unique name.");
|
DebugConsole.ThrowError("Error in " + ConfigFile + "! Each particle prefab must have a unique name.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
prefabs.Add(element.Name.ToString(), new ParticlePrefab(element));
|
prefabs.Add(element.Name.ToString(), new ParticlePrefab(element));
|
||||||
|
|||||||
@@ -101,6 +101,20 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector2 velocityChangeWater;
|
||||||
|
public Vector2 VelocityChangeWaterDisplay { get; private set; }
|
||||||
|
|
||||||
|
[Editable(ToolTip = "How much the velocity of the particle changes per second when in water."), Serialize("0.0,0.0", false)]
|
||||||
|
public Vector2 VelocityChangeWater
|
||||||
|
{
|
||||||
|
get { return velocityChangeWater; }
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
velocityChangeWater = value;
|
||||||
|
VelocityChangeWaterDisplay = ConvertUnits.ToDisplayUnits(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Editable(0.0f, 10000.0f, ToolTip = "Drag applied to the particle when it's moving through water."), Serialize(0.0f, false)]
|
[Editable(0.0f, 10000.0f, ToolTip = "Drag applied to the particle when it's moving through water."), Serialize(0.0f, false)]
|
||||||
public float CollisionRadius { get; private set; }
|
public float CollisionRadius { get; private set; }
|
||||||
|
|
||||||
@@ -164,6 +178,8 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
|
|
||||||
|
public readonly List<ParticleEmitterPrefab> SubEmitters = new List<ParticleEmitterPrefab>();
|
||||||
|
|
||||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -191,9 +207,20 @@ namespace Barotrauma.Particles
|
|||||||
case "animatedsprite":
|
case "animatedsprite":
|
||||||
Sprites.Add(new SpriteSheet(subElement));
|
Sprites.Add(new SpriteSheet(subElement));
|
||||||
break;
|
break;
|
||||||
|
case "particleemitter":
|
||||||
|
case "emitter":
|
||||||
|
case "subemitter":
|
||||||
|
SubEmitters.Add(new ParticleEmitterPrefab(subElement));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if velocity change in water is not given, it defaults to the normal velocity change
|
||||||
|
if (element.Attribute("velocitychangewater") == null)
|
||||||
|
{
|
||||||
|
VelocityChangeWater = VelocityChange;
|
||||||
|
}
|
||||||
|
|
||||||
if (element.Attribute("angularvelocity") != null)
|
if (element.Attribute("angularvelocity") != null)
|
||||||
{
|
{
|
||||||
AngularVelocityMin = element.GetAttributeFloat("angularvelocity", 0.0f);
|
AngularVelocityMin = element.GetAttributeFloat("angularvelocity", 0.0f);
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
public float EmitTimer;
|
public float EmitTimer;
|
||||||
|
|
||||||
[Editable(), Serialize("0.0,0.0", false)]
|
public float BurstTimer;
|
||||||
|
|
||||||
|
[Editable(), Serialize("0.0,360.0", false)]
|
||||||
public Vector2 AngleRange { get; private set; }
|
public Vector2 AngleRange { get; private set; }
|
||||||
|
|
||||||
[Editable(), Serialize("0.0,0.0", false)]
|
[Editable(), Serialize("0.0,0.0", false)]
|
||||||
@@ -26,8 +28,12 @@ namespace Barotrauma
|
|||||||
public Vector2 ScaleRange { get; private set; }
|
public Vector2 ScaleRange { get; private set; }
|
||||||
|
|
||||||
[Editable(), Serialize(0, false)]
|
[Editable(), Serialize(0, false)]
|
||||||
public int ParticleAmount { get; private set; }
|
public int ParticleBurstAmount { get; private set; }
|
||||||
[Editable(), Serialize(0.0f, false)]
|
|
||||||
|
[Editable(), Serialize(1.0f, false)]
|
||||||
|
public float ParticleBurstInterval { get; private set; }
|
||||||
|
|
||||||
|
[Editable(), Serialize(1.0f, false)]
|
||||||
public float ParticlesPerSecond { get; private set; }
|
public float ParticlesPerSecond { get; private set; }
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@@ -46,6 +52,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Emitter()
|
public Emitter()
|
||||||
{
|
{
|
||||||
|
ScaleRange = Vector2.One;
|
||||||
|
AngleRange = new Vector2(0.0f, 360.0f);
|
||||||
|
ParticleBurstAmount = 1;
|
||||||
|
ParticleBurstInterval = 1.0f;
|
||||||
|
|
||||||
SerializableProperties = SerializableProperty.GetProperties(this);
|
SerializableProperties = SerializableProperty.GetProperties(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,6 +221,8 @@ namespace Barotrauma
|
|||||||
if (selectedPrefab != null)
|
if (selectedPrefab != null)
|
||||||
{
|
{
|
||||||
emitter.EmitTimer += (float)deltaTime;
|
emitter.EmitTimer += (float)deltaTime;
|
||||||
|
emitter.BurstTimer += (float)deltaTime;
|
||||||
|
|
||||||
|
|
||||||
if (emitter.ParticlesPerSecond > 0)
|
if (emitter.ParticlesPerSecond > 0)
|
||||||
{
|
{
|
||||||
@@ -221,10 +234,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < emitter.ParticleAmount; i++)
|
if (emitter.BurstTimer > emitter.ParticleBurstInterval)
|
||||||
{
|
{
|
||||||
Emit(Vector2.Zero);
|
for (int i = 0; i < emitter.ParticleBurstAmount; i++)
|
||||||
|
{
|
||||||
|
Emit(Vector2.Zero);
|
||||||
|
}
|
||||||
|
emitter.BurstTimer = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.ParticleManager.Update((float)deltaTime);
|
GameMain.ParticleManager.Update((float)deltaTime);
|
||||||
|
|||||||
Reference in New Issue
Block a user