Skip to content

Commit

Permalink
particles
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeIpsum committed Nov 6, 2019
1 parent e4e20be commit cf32626
Show file tree
Hide file tree
Showing 3 changed files with 431 additions and 0 deletions.
139 changes: 139 additions & 0 deletions WeWereBound/Particles/Particle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;

namespace WeWereBound
{
public struct Particle
{
public Entity Track;
public ParticleType Type;
public MTexture Source;

public bool Active;
public Color Color;
public Color StartColor;
public Vector2 Position;
public Vector2 Speed;
public float Size;
public float StartSize;
public float Life;
public float StartLife;
public float ColorSwitch;
public float Rotation;
public float Spin;

public bool SimulateFor(float duration)
{
if (duration > Life)
{
Life = 0;
Active = false;
return false;
}
else
{
var dt = GameEngine.TimeRate * (GameEngine.Instance.TargetElapsedTime.Milliseconds / 1000f);
if (dt > 0)
for (var t = 0f; t < duration; t += dt)
Update(dt);

return true;
}
}

public void Update(float? delta = null)
{
var dt = 0f;
if (delta.HasValue)
dt = delta.Value;
else
dt = (Type.UseActualDeltaTime ? GameEngine.RawDeltaTime : GameEngine.DeltaTime);

var ease = Life / StartLife;

//Life
Life -= dt;
if (Life <= 0)
{
Active = false;
return;
}

//Spin
if (Type.RotationMode == ParticleType.RotationModes.SameAsDirection)
{
if (Speed != Vector2.Zero)
Rotation = Speed.Angle();
}
else
Rotation += Spin * dt;

//Fade
float alpha;
if (Type.FadeMode == ParticleType.FadeModes.Linear)
alpha = ease;
else if (Type.FadeMode == ParticleType.FadeModes.Late)
alpha = Math.Min(1f, ease / .25f);
else if (Type.FadeMode == ParticleType.FadeModes.InAndOut)
{
if (ease > .75f)
alpha = 1 - ((ease - .75f) / .25f);
else if (ease < .25f)
alpha = ease / .25f;
else
alpha = 1f;
}
else
alpha = 1f;


//Color switch with alpha
if (alpha == 0)
Color = Color.Transparent;
else
{
if (Type.ColorMode == ParticleType.ColorModes.Static)
Color = StartColor;
else if (Type.ColorMode == ParticleType.ColorModes.Fade)
Color = Color.Lerp(Type.Color2, StartColor, ease);
else if (Type.ColorMode == ParticleType.ColorModes.Blink)
Color = (Calc.BetweenInterval(Life, .1f) ? StartColor : Type.Color2);
else if (Type.ColorMode == ParticleType.ColorModes.Choose)
Color = StartColor;

if (alpha < 1f)
Color *= alpha;
}

//Speed
Position += Speed * dt;
Speed += Type.Acceleration * dt;
Speed = Calc.Approach(Speed, Vector2.Zero, Type.Friction * dt);
if (Type.SpeedMultiplier != 1)
Speed *= (float)Math.Pow(Type.SpeedMultiplier, dt);

//Scale Out
if (Type.ScaleOut)
Size = StartSize * Ease.CubeOut(ease);
}

public void Render()
{
var renderAt = new Vector2((int)Position.X, (int)Position.Y);
if (Track != null)
renderAt += Track.Position;

Draw.SpriteBatch.Draw(Source.Texture, renderAt, Source.ClipRect, Color, Rotation, Source.Center, Size, SpriteEffects.None, 0);
}

public void Render(float alpha)
{
var renderAt = new Vector2((int)Position.X, (int)Position.Y);
if (Track != null)
renderAt += Track.Position;

Draw.SpriteBatch.Draw(Source.Texture, renderAt, Source.ClipRect, Color * alpha, Rotation, Source.Center, Size, SpriteEffects.None, 0);
}
}
}
134 changes: 134 additions & 0 deletions WeWereBound/Particles/ParticleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Microsoft.Xna.Framework;
using System;

namespace WeWereBound
{
public class ParticleSystem : Entity
{
private Particle[] particles;
private int nextSlot;

public ParticleSystem(int depth, int maxParticles)
: base()
{
particles = new Particle[maxParticles];
Depth = depth;
}

public void Clear()
{
for (int i = 0; i < particles.Length; i++)
particles[i].Active = false;
}

public void ClearRect(Rectangle rect, bool inside)
{
for (int i = 0; i < particles.Length; i++)
{
var pos = particles[i].Position;
var isInside = (pos.X > rect.Left && pos.Y > rect.Top && pos.X < rect.Right && pos.Y < rect.Bottom);

if (isInside == inside)
particles[i].Active = false;
}
}

public override void Update()
{
for (int i = 0; i < particles.Length; i++)
if (particles[i].Active)
particles[i].Update();
}

public override void Render()
{
foreach (var p in particles)
if (p.Active)
p.Render();
}

public void Render(float alpha)
{
foreach (var p in particles)
if (p.Active)
p.Render(alpha);
}

public void Simulate(float duration, float interval, Action<ParticleSystem> emitter)
{
var delta = 0.016f;
for (float time = 0f; time < duration; time += delta)
{
if ((int)((time - delta) / interval) < (int)(time / interval))
emitter(this);

for (int i = 0; i < particles.Length; i++)
if (particles[i].Active)
particles[i].Update(delta);
}
}

public void Add(Particle particle)
{
particles[nextSlot] = particle;
nextSlot = (nextSlot + 1) % particles.Length;
}

public void Emit(ParticleType type, Vector2 position)
{
type.Create(ref particles[nextSlot], position);
nextSlot = (nextSlot + 1) % particles.Length;
}

public void Emit(ParticleType type, Vector2 position, float direction)
{
type.Create(ref particles[nextSlot], position, direction);
nextSlot = (nextSlot + 1) % particles.Length;
}

public void Emit(ParticleType type, Vector2 position, Color color)
{
type.Create(ref particles[nextSlot], position, color);
nextSlot = (nextSlot + 1) % particles.Length;
}

public void Emit(ParticleType type, Vector2 position, Color color, float direction)
{
type.Create(ref particles[nextSlot], position, color, direction);
nextSlot = (nextSlot + 1) % particles.Length;
}

public void Emit(ParticleType type, int amount, Vector2 position, Vector2 positionRange)
{
for (int i = 0; i < amount; i++)
Emit(type, Calc.Random.Range(position - positionRange, position + positionRange));
}

public void Emit(ParticleType type, int amount, Vector2 position, Vector2 positionRange, float direction)
{
for (int i = 0; i < amount; i++)
Emit(type, Calc.Random.Range(position - positionRange, position + positionRange), direction);
}

public void Emit(ParticleType type, int amount, Vector2 position, Vector2 positionRange, Color color)
{
for (int i = 0; i < amount; i++)
Emit(type, Calc.Random.Range(position - positionRange, position + positionRange), color);
}

public void Emit(ParticleType type, int amount, Vector2 position, Vector2 positionRange, Color color, float direction)
{
for (int i = 0; i < amount; i++)
Emit(type, Calc.Random.Range(position - positionRange, position + positionRange), color, direction);
}

public void Emit(ParticleType type, Entity track, int amount, Vector2 position, Vector2 positionRange, float direction)
{
for (int i = 0; i < amount; i++)
{
type.Create(ref particles[nextSlot], track, Calc.Random.Range(position - positionRange, position + positionRange), direction, type.Color);
nextSlot = (nextSlot + 1) % particles.Length;
}
}
}
}
Loading

0 comments on commit cf32626

Please sign in to comment.