- The emission rate of ParticleEmitters can be set as particles per second (instead of particles per frame).
- Particles that are outside the sub aren't visible inside hulls even if they overlap with the sub. - ParticleManager takes the movement of the particles into account when determining which particles to cull. For example, a particle that will move upwards can be emitted even if it's below the camera view.
This commit is contained in:
@@ -8,7 +8,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private Sound sound;
|
private Sound sound;
|
||||||
|
|
||||||
private ParticleEmitterPrefab particleEmitterPrefab;
|
private ParticleEmitter particleEmitterPrefab;
|
||||||
|
|
||||||
partial void InitProjSpecific(XElement element)
|
partial void InitProjSpecific(XElement element)
|
||||||
{
|
{
|
||||||
@@ -23,18 +23,18 @@ namespace Barotrauma
|
|||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "particleemitter":
|
case "particleemitter":
|
||||||
particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
|
particleEmitterPrefab = new ParticleEmitter(subElement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void DamageParticles(Vector2 worldPosition)
|
partial void DamageParticles(float deltaTime, Vector2 worldPosition)
|
||||||
{
|
{
|
||||||
if (particleEmitterPrefab != null)
|
if (particleEmitterPrefab != null)
|
||||||
{
|
{
|
||||||
particleEmitterPrefab.Emit(worldPosition);
|
particleEmitterPrefab.Emit(deltaTime, worldPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sound != null)
|
if (sound != null)
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ namespace Barotrauma.Lights
|
|||||||
|
|
||||||
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
lightEffect.World = Matrix.CreateTranslation(offset) * transform;
|
||||||
|
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
|
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
|
||||||
|
|
||||||
if (Character.Controlled != null)
|
if (Character.Controlled != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ namespace Barotrauma.Particles
|
|||||||
get { return velocity; }
|
get { return velocity; }
|
||||||
set { velocity = value; }
|
set { velocity = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Hull CurrentHull
|
||||||
|
{
|
||||||
|
get { return currentHull; }
|
||||||
|
}
|
||||||
|
|
||||||
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null)
|
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace Barotrauma.Particles
|
namespace Barotrauma.Particles
|
||||||
{
|
{
|
||||||
class ParticleEmitterPrefab
|
class ParticleEmitter
|
||||||
{
|
{
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
|
|
||||||
@@ -15,10 +15,14 @@ namespace Barotrauma.Particles
|
|||||||
public readonly float VelocityMin, VelocityMax;
|
public readonly float VelocityMin, VelocityMax;
|
||||||
|
|
||||||
public readonly float ScaleMin, ScaleMax;
|
public readonly float ScaleMin, ScaleMax;
|
||||||
|
|
||||||
|
public readonly int ParticleAmount;
|
||||||
|
|
||||||
public readonly float ParticleAmount;
|
public readonly float ParticlesPerSecond;
|
||||||
|
|
||||||
|
private float emitTimer;
|
||||||
|
|
||||||
public ParticleEmitterPrefab(XElement element)
|
public ParticleEmitter(XElement element)
|
||||||
{
|
{
|
||||||
Name = element.Name.ToString();
|
Name = element.Name.ToString();
|
||||||
|
|
||||||
@@ -60,22 +64,40 @@ namespace Barotrauma.Particles
|
|||||||
VelocityMax = VelocityMin;
|
VelocityMax = VelocityMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleAmount = ToolBox.GetAttributeInt(element, "particleamount", 1);
|
ParticlesPerSecond = ToolBox.GetAttributeInt(element, "particlespersecond", 0);
|
||||||
|
ParticleAmount = ToolBox.GetAttributeInt(element, "particleamount", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(Vector2 position, Hull hullGuess = null)
|
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null)
|
||||||
{
|
{
|
||||||
|
emitTimer += deltaTime;
|
||||||
|
|
||||||
|
if (ParticlesPerSecond > 0)
|
||||||
|
{
|
||||||
|
float emitInterval = 1.0f / ParticlesPerSecond;
|
||||||
|
while (emitTimer > emitInterval)
|
||||||
|
{
|
||||||
|
Emit(position, hullGuess);
|
||||||
|
emitTimer -= emitInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i<ParticleAmount; i++)
|
for (int i = 0; i<ParticleAmount; i++)
|
||||||
{
|
{
|
||||||
float angle = Rand.Range(AngleMin, AngleMax);
|
Emit(position, hullGuess);
|
||||||
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Rand.Range(VelocityMin, VelocityMax);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab, position, velocity, 0.0f, hullGuess);
|
private void Emit(Vector2 position, Hull hullGuess = null)
|
||||||
|
{
|
||||||
|
float angle = Rand.Range(AngleMin, AngleMax);
|
||||||
|
Vector2 velocity = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * Rand.Range(VelocityMin, VelocityMax);
|
||||||
|
|
||||||
if (particle!=null)
|
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab, position, velocity, 0.0f, hullGuess);
|
||||||
{
|
|
||||||
particle.Size *= Rand.Range(ScaleMin, ScaleMax);
|
if (particle != null)
|
||||||
}
|
{
|
||||||
|
particle.Size *= Rand.Range(ScaleMin, ScaleMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,19 +66,26 @@ namespace Barotrauma.Particles
|
|||||||
|
|
||||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation = 0.0f, Hull hullGuess = null)
|
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation = 0.0f, Hull hullGuess = null)
|
||||||
{
|
{
|
||||||
if (!Submarine.RectContains(MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist), position)) return null;
|
|
||||||
//if (!cam.WorldView.Contains(position)) return null;
|
|
||||||
|
|
||||||
if (particleCount >= MaxParticles) return null;
|
if (particleCount >= MaxParticles) return null;
|
||||||
|
|
||||||
|
//endPos = x + vt + 1/2 * at^2
|
||||||
|
Vector2 particleEndPos = position + speed * prefab.LifeTime + 0.5f * prefab.VelocityChange * prefab.LifeTime * prefab.LifeTime;
|
||||||
|
|
||||||
|
Vector2 minPos = new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
|
||||||
|
Vector2 maxPos = new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
|
||||||
|
|
||||||
|
Rectangle expandedViewRect = MathUtils.ExpandRect(cam.WorldView, MaxOutOfViewDist);
|
||||||
|
|
||||||
|
if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) return null;
|
||||||
|
if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) return null;
|
||||||
|
|
||||||
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
if (particles[particleCount] == null) particles[particleCount] = new Particle();
|
||||||
|
|
||||||
particles[particleCount].Init(prefab, position, speed, rotation, hullGuess);
|
particles[particleCount].Init(prefab, position, speed, rotation, hullGuess);
|
||||||
|
|
||||||
particleCount++;
|
particleCount++;
|
||||||
|
|
||||||
return particles[particleCount-1];
|
return particles[particleCount - 1];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParticlePrefab FindPrefab(string prefabName)
|
public ParticlePrefab FindPrefab(string prefabName)
|
||||||
@@ -131,7 +138,7 @@ namespace Barotrauma.Particles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool inWater, ParticleBlendState blendState)
|
public void Draw(SpriteBatch spriteBatch, bool inWater, bool? inSub, ParticleBlendState blendState)
|
||||||
{
|
{
|
||||||
ParticlePrefab.DrawTargetType drawTarget = inWater ? ParticlePrefab.DrawTargetType.Water : ParticlePrefab.DrawTargetType.Air;
|
ParticlePrefab.DrawTargetType drawTarget = inWater ? ParticlePrefab.DrawTargetType.Water : ParticlePrefab.DrawTargetType.Air;
|
||||||
|
|
||||||
@@ -139,6 +146,7 @@ namespace Barotrauma.Particles
|
|||||||
{
|
{
|
||||||
if (particles[i].BlendState != blendState) continue;
|
if (particles[i].BlendState != blendState) continue;
|
||||||
if (!particles[i].DrawTarget.HasFlag(drawTarget)) continue;
|
if (!particles[i].DrawTarget.HasFlag(drawTarget)) continue;
|
||||||
|
if (inSub.HasValue && (particles[i].CurrentHull == null) == inSub.Value) continue;
|
||||||
|
|
||||||
particles[i].Draw(spriteBatch);
|
particles[i].Draw(spriteBatch);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,27 @@ namespace Barotrauma
|
|||||||
Level.Loaded.DrawBack(graphics, spriteBatch, cam, BackgroundCreatureManager);
|
Level.Loaded.DrawBack(graphics, spriteBatch, cam, BackgroundCreatureManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
|
BlendState.NonPremultiplied,
|
||||||
|
null, DepthStencilState.DepthRead, null, null,
|
||||||
|
cam.Transform);
|
||||||
|
#else
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
|
BlendState.AlphaBlend,
|
||||||
|
null, DepthStencilState.DepthRead, null, null,
|
||||||
|
cam.Transform);
|
||||||
|
#endif
|
||||||
|
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.AlphaBlend);
|
||||||
|
spriteBatch.End();
|
||||||
|
|
||||||
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
|
BlendState.Additive,
|
||||||
|
null, DepthStencilState.Default, null, null,
|
||||||
|
cam.Transform);
|
||||||
|
GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
|
||||||
|
spriteBatch.End();
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||||
BlendState.AlphaBlend,
|
BlendState.AlphaBlend,
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
@@ -181,14 +202,14 @@ namespace Barotrauma
|
|||||||
null, DepthStencilState.DepthRead, null, null,
|
null, DepthStencilState.DepthRead, null, null,
|
||||||
cam.Transform);
|
cam.Transform);
|
||||||
#endif
|
#endif
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.AlphaBlend);
|
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.AlphaBlend);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
BlendState.Additive,
|
BlendState.Additive,
|
||||||
null, DepthStencilState.Default, null, null,
|
null, DepthStencilState.Default, null, null,
|
||||||
cam.Transform);
|
cam.Transform);
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.Additive);
|
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
@@ -211,14 +232,14 @@ namespace Barotrauma
|
|||||||
cam.Transform);
|
cam.Transform);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.AlphaBlend);
|
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.AlphaBlend);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||||
BlendState.Additive,
|
BlendState.Additive,
|
||||||
null, DepthStencilState.DepthRead, null, null,
|
null, DepthStencilState.DepthRead, null, null,
|
||||||
cam.Transform);
|
cam.Transform);
|
||||||
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
|
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
|
||||||
spriteBatch.End();
|
spriteBatch.End();
|
||||||
|
|
||||||
if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
|
if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
|
||||||
|
|||||||
@@ -270,8 +270,8 @@
|
|||||||
<StatusEffect type="OnUse" target="This" IsOn="true"/>
|
<StatusEffect type="OnUse" target="This" IsOn="true"/>
|
||||||
|
|
||||||
<StatusEffect type="OnActive" target="This" Condition="-1.0">
|
<StatusEffect type="OnActive" target="This" Condition="-1.0">
|
||||||
<ParticleEmitter particle="flare"/>
|
<ParticleEmitter particle="flare" particlespersecond="30"/>
|
||||||
<ParticleEmitter particle="bubbles"/>
|
<ParticleEmitter particle="bubbles" particlespersecond="30"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
|
|
||||||
<StatusEffect type="OnBroken" target="This" IsOn="false"/>
|
<StatusEffect type="OnBroken" target="This" IsOn="false"/>
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public AttackResult DoDamage(IDamageable attacker, IDamageable target, Vector2 worldPosition, float deltaTime, bool playSound = true)
|
public AttackResult DoDamage(IDamageable attacker, IDamageable target, Vector2 worldPosition, float deltaTime, bool playSound = true)
|
||||||
{
|
{
|
||||||
DamageParticles(worldPosition);
|
DamageParticles(deltaTime, worldPosition);
|
||||||
|
|
||||||
var attackResult = target.AddDamage(attacker, worldPosition, this, deltaTime, playSound);
|
var attackResult = target.AddDamage(attacker, worldPosition, this, deltaTime, playSound);
|
||||||
|
|
||||||
@@ -168,6 +168,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return attackResult;
|
return attackResult;
|
||||||
}
|
}
|
||||||
partial void DamageParticles(Vector2 worldPosition);
|
partial void DamageParticles(float deltaTime, Vector2 worldPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Barotrauma
|
|||||||
private List<RelatedItem> requiredItems;
|
private List<RelatedItem> requiredItems;
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
private List<ParticleEmitterPrefab> particleEmitters;
|
private List<ParticleEmitter> particleEmitters;
|
||||||
|
|
||||||
private Sound sound;
|
private Sound sound;
|
||||||
#endif
|
#endif
|
||||||
@@ -77,7 +77,7 @@ namespace Barotrauma
|
|||||||
requiredItems = new List<RelatedItem>();
|
requiredItems = new List<RelatedItem>();
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
particleEmitters = new List<ParticleEmitterPrefab>();
|
particleEmitters = new List<ParticleEmitter>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IEnumerable<XAttribute> attributes = element.Attributes();
|
IEnumerable<XAttribute> attributes = element.Attributes();
|
||||||
@@ -179,7 +179,7 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
case "particleemitter":
|
case "particleemitter":
|
||||||
particleEmitters.Add(new ParticleEmitterPrefab(subElement));
|
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -280,9 +280,9 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if CLIENT
|
#if CLIENT
|
||||||
foreach (ParticleEmitterPrefab emitter in particleEmitters)
|
foreach (ParticleEmitter emitter in particleEmitters)
|
||||||
{
|
{
|
||||||
emitter.Emit(entity.WorldPosition, hull);
|
emitter.Emit(deltaTime, entity.WorldPosition, hull);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -331,8 +331,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Couldn't apply value "+value.ToString()+" ("+type+") to property \""+property.Name+"\" ("+property.GetValue().GetType()+")! "
|
DebugConsole.ThrowError("Couldn't apply value " + value.ToString() + " (" + type + ") to property \"" + property.Name + "\" (" + property.GetValue().GetType() + ")! "
|
||||||
+"Make sure the type of the value set in the config files matches the type of the property.");
|
+ "Make sure the type of the value set in the config files matches the type of the property.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user