Skip to content

Commit bf3364b

Browse files
committed
particle system refactor, allowing particles to spawn more particles
1 parent 835f1de commit bf3364b

File tree

10 files changed

+97
-37
lines changed

10 files changed

+97
-37
lines changed

BenMakesGames.PlayPlayMini.GraphicsExtensions/BenMakesGames.PlayPlayMini.GraphicsExtensions.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Company>Ben Hendel-Doying</Company>
66
<Description>Some GraphicsManager extensions for PlayPlayMini.</Description>
77
<Copyright>2023-2025 Ben Hendel-Doying</Copyright>
8-
<Version>6.1.0</Version>
8+
<Version>6.2.0</Version>
99

1010
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1111
<PackageTags>monogame playplaymini graphics extensions animations text</PackageTags>

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/FlashOfInsight.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
55

6+
/// <summary>
7+
/// The entire screen goes white; the white then parts in half, each half receding to the top and bottom of the screen.
8+
/// The total effect takes only a tenth of a second.
9+
/// </summary>
610
public sealed class FlashOfInsight: IParticle
711
{
812
private Color Color { get; }
@@ -17,7 +21,7 @@ public FlashOfInsight(Color color)
1721
}
1822

1923
/// <inheritdoc />
20-
public void Update(GameTime gameTime)
24+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
2125
{
2226
TTL -= gameTime.ElapsedGameTime.TotalSeconds;
2327
}

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/FloatAwayPicture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public sealed class FloatAwayPicture: IParticle
2121
public int Y => (int)(StartingY - Math.Sin(Angle) * TimeAlive * Speed);
2222

2323
/// <inheritdoc />
24-
public void Update(GameTime gameTime)
24+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
2525
{
2626
TimeAlive += gameTime.ElapsedGameTime.TotalSeconds;
2727
}

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/FloatAwayText.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
66

7+
/// <summary>
8+
/// A piece of text that floats away from a starting position at a specified angle and speed.
9+
/// </summary>
710
public sealed class FloatAwayText: IParticle
811
{
912
public required string Text { get; init; }
@@ -23,7 +26,7 @@ public sealed class FloatAwayText: IParticle
2326
public int Y => (int)(StartingY - Math.Sin(Angle) * TimeAlive * Speed);
2427

2528
/// <inheritdoc />
26-
public void Update(GameTime gameTime)
29+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
2730
{
2831
TimeAlive += gameTime.ElapsedGameTime.TotalSeconds;
2932
}

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/GlassShard.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
66

7+
/// <summary>
8+
/// A tumbling shard of glass that launches away from its starting point, and falls under gravity.
9+
/// </summary>
710
public sealed class GlassShard : IParticle
811
{
912
/// <inheritdoc />
@@ -74,7 +77,7 @@ public void Draw(GraphicsManager graphics)
7477
}
7578

7679
/// <inheritdoc />
77-
public void Update(GameTime gameTime)
80+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
7881
{
7982
YSpeed += 0.2 * gameTime.ElapsedGameTime.TotalSeconds * 60;
8083

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/IParticle.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using BenMakesGames.PlayPlayMini.Services;
1+
using System.Collections.Generic;
2+
using BenMakesGames.PlayPlayMini.Services;
23
using Microsoft.Xna.Framework;
34

45
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
@@ -26,8 +27,9 @@ public interface IParticle
2627
/// <summary>
2728
/// Update the particle's state.
2829
/// </summary>
30+
/// <param name="particleSpawner"></param>
2931
/// <param name="gameTime"></param>
30-
void Update(GameTime gameTime);
32+
void Update(IParticleSpawner particleSpawner, GameTime gameTime);
3133

3234
/// <summary>
3335
/// Draw the particle.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using BenMakesGames.PlayPlayMini.Services;
3+
using Microsoft.Xna.Framework;
4+
5+
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
6+
7+
public interface IParticleSpawner
8+
{
9+
/// <summary>
10+
/// Queues particles to be added in the next Update cycle.
11+
/// </summary>
12+
/// <param name="particle"></param>
13+
void AddParticles(params IEnumerable<IParticle> particle);
14+
}
15+
16+
/// <summary>
17+
/// For updating and drawing a collection of particles.
18+
/// </summary>
19+
/// <remarks>
20+
/// If you want different layers of particles (e.g. background, foreground), create multiple instances of this class,
21+
/// update them all, and draw them in the desired order.
22+
/// </remarks>
23+
public sealed class ParticleCollection: IParticleSpawner
24+
{
25+
private const int InitialParticleCapacity = 256;
26+
private const int InitialSpawnQueueCapacity = 128;
27+
28+
private List<IParticle> Particles { get; } = new(InitialParticleCapacity);
29+
private List<IParticle> SpawnQueue { get; } = new(InitialSpawnQueueCapacity);
30+
31+
/// <inheritdoc />
32+
public void AddParticles(params IEnumerable<IParticle> particle)
33+
{
34+
SpawnQueue.AddRange(particle);
35+
}
36+
37+
/// <summary>
38+
/// Updates all particles in the collection.
39+
/// </summary>
40+
/// <remarks>
41+
/// For better performance, call this in your GameState's FixedUpdate method rather than its Update method.
42+
/// </remarks>
43+
/// <param name="gameTime"></param>
44+
public void Update(GameTime gameTime)
45+
{
46+
Particles.AddRange(SpawnQueue);
47+
48+
SpawnQueue.Clear();
49+
50+
for(int i = Particles.Count - 1; i >= 0; i--)
51+
{
52+
var particle = Particles[i];
53+
54+
if (particle.IsAlive)
55+
particle.Update(this, gameTime);
56+
else
57+
Particles.RemoveAt(i);
58+
}
59+
}
60+
61+
/// <summary>
62+
/// Draws all particles in the collection.
63+
/// </summary>
64+
/// <remarks>
65+
/// Call in your GameState's Draw method.
66+
/// </remarks>
67+
/// <param name="graphics"></param>
68+
public void Draw(GraphicsManager graphics)
69+
{
70+
foreach (var particle in Particles)
71+
particle.Draw(graphics);
72+
}
73+
}

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/Particles.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/Snow.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace BenMakesGames.PlayPlayMini.GraphicsExtensions.ParticleEffects;
66

7+
/// <summary>
8+
/// A particle of snow that falls to the ground, waving slightly as it falls.
9+
/// </summary>
710
public sealed class Snow: IParticle
811
{
912
private Color Color { get; }
@@ -29,7 +32,7 @@ public Snow(Color color, int maxY, int graphicsWidth)
2932
}
3033

3134
/// <inheritdoc />
32-
public void Update(GameTime gameTime)
35+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
3336
{
3437
X -= gameTime.ElapsedGameTime.TotalSeconds * 4 * Size * Speed;
3538
Y += gameTime.ElapsedGameTime.TotalSeconds * 16 * Size * Speed;

BenMakesGames.PlayPlayMini.GraphicsExtensions/ParticleEffects/TumblingSprite.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void Draw(GraphicsManager graphics)
3838
}
3939

4040
/// <inheritdoc />
41-
public void Update(GameTime gameTime)
41+
public void Update(IParticleSpawner particleSpawner, GameTime gameTime)
4242
{
4343
CenterX += XVelocity * gameTime.ElapsedGameTime.TotalSeconds * 60;
4444
CenterY += YVelocity * gameTime.ElapsedGameTime.TotalSeconds * 60;

0 commit comments

Comments
 (0)