1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
4 using System.Collections.Generic;
23 private const int MaxOutOfViewDist = 500;
25 private int particleCount;
28 get {
return particleCount; }
31 private int maxParticles;
34 get {
return maxParticles; }
37 if (maxParticles == value || value < 4) {
return; }
40 for (
int i = 0; i < Math.Min(maxParticles, value); i++)
42 newParticles[i] = particles[i];
45 particleCount = Math.Min(particleCount, value);
46 particles = newParticles;
49 var oldParticlesInCreationOrder = particlesInCreationOrder.ToList();
50 particlesInCreationOrder.Clear();
51 foreach (var particle
in oldParticlesInCreationOrder)
53 if (particles.Contains(particle))
55 particlesInCreationOrder.AddLast(particle);
67 private readonly LinkedList<Particle> particlesInCreationOrder =
new LinkedList<Particle>();
81 MaxParticles = GameSettings.CurrentConfig.Graphics.ParticleLimit;
84 public Particle CreateParticle(
string prefabName, Vector2 position,
float angle,
float speed,
Hull hullGuess =
null,
float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints =
null)
86 return CreateParticle(prefabName, position,
new Vector2((
float)Math.Cos(angle), (
float)-Math.Sin(angle)) * speed, angle, hullGuess, collisionIgnoreTimer, tracerPoints: tracerPoints);
89 public Particle CreateParticle(
string prefabName, Vector2 position, Vector2 velocity,
float rotation = 0.0f,
Hull hullGuess =
null,
float collisionIgnoreTimer = 0f, Tuple<Vector2, Vector2> tracerPoints =
null)
95 DebugConsole.ThrowError(
"Particle prefab \"" + prefabName +
"\" not found!");
98 return CreateParticle(prefab, position, velocity, rotation, hullGuess, collisionIgnoreTimer: collisionIgnoreTimer, tracerPoints:tracerPoints);
103 if (prefab ==
null || prefab.
Sprites.Count == 0) {
return null; }
106 for (
int i = 0; i < particleCount; i++)
120 Vector2 minPos =
new Vector2(Math.Min(position.X, particleEndPos.X), Math.Min(position.Y, particleEndPos.Y));
121 Vector2 maxPos =
new Vector2(Math.Max(position.X, particleEndPos.X), Math.Max(position.Y, particleEndPos.Y));
123 if (tracerPoints !=
null)
125 minPos =
new Vector2(
126 Math.Min(Math.Min(minPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
127 Math.Min(Math.Min(minPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
128 maxPos =
new Vector2(
129 Math.Max(Math.Max(maxPos.X, tracerPoints.Item1.X), tracerPoints.Item2.X),
130 Math.Max(Math.Max(maxPos.Y, tracerPoints.Item1.Y), tracerPoints.Item2.Y));
137 if (minPos.X > expandedViewRect.Right || maxPos.X < expandedViewRect.X) {
return null; }
138 if (minPos.Y > expandedViewRect.Y || maxPos.Y < expandedViewRect.Y - expandedViewRect.Height) {
return null; }
141 if (particles[particleCount] ==
null) { particles[particleCount] =
new Particle(); }
142 Particle particle = particles[particleCount];
144 particle.
Init(prefab, position, velocity, rotation, hullGuess, drawOrder, collisionIgnoreTimer, lifeTimeMultiplier, tracerPoints: tracerPoints);
146 particlesInCreationOrder.AddFirst(particle);
162 private void RemoveParticle(
int index)
164 particlesInCreationOrder.Remove(particles[index]);
167 (particles[particleCount], particles[index]) = (particles[index], particles[particleCount]);
173 for (
int i = 0; i < particleCount; i++)
175 if (particles[i] == particle)
185 MaxParticles = GameSettings.CurrentConfig.Graphics.ParticleLimit;
187 for (
int i = 0; i < particleCount; i++)
196 DebugConsole.ThrowError(
"Particle update failed", e);
200 if (
remove) { RemoveParticle(i); }
206 for (
int i = 0; i < particleCount; i++)
214 Dictionary<ParticlePrefab, int> activeParticles =
new Dictionary<ParticlePrefab, int>();
215 for (
int i = 0; i < particleCount; i++)
217 if (!activeParticles.ContainsKey(particles[i].
Prefab)) activeParticles[particles[i].
Prefab] = 0;
218 activeParticles[particles[i].Prefab]++;
220 return activeParticles;
223 public void Draw(SpriteBatch spriteBatch,
bool inWater,
bool? inSub,
ParticleBlendState blendState,
bool? background =
false)
227 foreach (var particle
in particlesInCreationOrder)
229 if (particle.BlendState != blendState) {
continue; }
231 if ((particle.DrawTarget & drawTarget) == 0) {
continue; }
234 bool isOutside = particle.CurrentHull ==
null;
235 if (particle.DrawOrder !=
ParticleDrawOrder.Foreground && isOutside == inSub.Value)
240 if (background.HasValue)
243 if (background.Value != isBackgroundParticle) {
continue; }
245 particle.Draw(spriteBatch);
252 particlesInCreationOrder.Clear();
257 if (particles ==
null) {
return; }
258 for (
int i = particles.Length - 1; i >= 0; i--)
260 if (particles[i]?.
Prefab == prefab)
262 if (i < particleCount) { particleCount--; }
264 particlesInCreationOrder.Remove(particles[particleCount]);
265 Particle swap = particles[particleCount];
266 particles[particleCount] =
null;
UpdateResult Update(float deltaTime)
void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess=null, ParticleDrawOrder drawOrder=ParticleDrawOrder.Default, float collisionIgnoreTimer=0f, float lifeTimeMultiplier=1f, Tuple< Vector2, Vector2 > tracerPoints=null)
Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed, Hull hullGuess=null, float collisionIgnoreTimer=0f, Tuple< Vector2, Vector2 > tracerPoints=null)
void RemoveByPrefab(ParticlePrefab prefab)
Dictionary< ParticlePrefab, int > CountActiveParticles()
void RemoveParticle(Particle particle)
void Draw(SpriteBatch spriteBatch, bool inWater, bool? inSub, ParticleBlendState blendState, bool? background=false)
static List< ParticlePrefab > GetPrefabList()
Particle CreateParticle(string prefabName, Vector2 position, Vector2 velocity, float rotation=0.0f, Hull hullGuess=null, float collisionIgnoreTimer=0f, Tuple< Vector2, Vector2 > tracerPoints=null)
ParticleManager(Camera cam)
static ParticlePrefab FindPrefab(string prefabName)
Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation=0.0f, Hull hullGuess=null, ParticleDrawOrder drawOrder=ParticleDrawOrder.Default, float collisionIgnoreTimer=0f, float lifeTimeMultiplier=1f, Tuple< Vector2, Vector2 > tracerPoints=null)
void Update(float deltaTime)
static readonly PrefabCollection< ParticlePrefab > Prefabs
readonly List< Sprite > Sprites
Vector2 CalculateEndPosition(Vector2 startPosition, Vector2 velocity)