-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* bring over particle system. * added random class
- Loading branch information
Showing
4 changed files
with
309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using System; | ||
using Microsoft.Xna.Framework; | ||
|
||
namespace CS5410 | ||
{ | ||
/// <summary> | ||
/// Expands upon some of the features the .NET Random class does: | ||
/// | ||
/// *NextRange : Generate a random number within some range | ||
/// *NextGaussian : Generate a normally distributed random number | ||
/// | ||
/// </summary> | ||
class MyRandom : Random | ||
{ | ||
|
||
/// <summary> | ||
/// Generates a random number in the range or [Min,Max] | ||
/// </summary> | ||
public float nextRange(float min, float max) | ||
{ | ||
return MathHelper.Lerp(min, max, (float)this.NextDouble()); | ||
} | ||
|
||
/// <summary> | ||
/// Generate a random vector about a unit circle | ||
/// </summary> | ||
public Vector2 nextCircleVector() | ||
{ | ||
float angle = (float)(this.NextDouble() * 2.0 * Math.PI); | ||
float x = (float)Math.Cos(angle); | ||
float y = (float)Math.Sin(angle); | ||
|
||
return new Vector2(x, y); | ||
} | ||
|
||
/// <summary> | ||
/// Generate a normally distributed random number. Derived from a Wiki reference on | ||
/// how to do this. | ||
/// </summary> | ||
public double nextGaussian(double mean, double stdDev) | ||
{ | ||
if (this.usePrevious) | ||
{ | ||
this.usePrevious = false; | ||
return mean + y2 * stdDev; | ||
} | ||
this.usePrevious = true; | ||
|
||
double x1 = 0.0; | ||
double x2 = 0.0; | ||
double y1 = 0.0; | ||
double z = 0.0; | ||
|
||
do | ||
{ | ||
x1 = 2.0 * this.NextDouble() - 1.0; | ||
x2 = 2.0 * this.NextDouble() - 1.0; | ||
z = (x1 * x1) + (x2 * x2); | ||
} | ||
while (z >= 1.0); | ||
|
||
z = Math.Sqrt((-2.0 * Math.Log(z)) / z); | ||
y1 = x1 * z; | ||
y2 = x2 * z; | ||
|
||
return mean + y1 * stdDev; | ||
} | ||
|
||
/// <summary> | ||
/// Keep this around to optimize gaussian calculation performance. | ||
/// </summary> | ||
private double y2; | ||
private bool usePrevious { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using Microsoft.Xna.Framework; | ||
using System; | ||
|
||
namespace CS5410 | ||
{ | ||
public class Particle | ||
{ | ||
public long name; | ||
public Vector2 size; | ||
public Vector2 center; | ||
public float rotation; | ||
public Color color; // Added color property | ||
|
||
private Vector2 direction; | ||
private float speed; | ||
private TimeSpan lifetime; | ||
private TimeSpan alive = TimeSpan.Zero; | ||
private static long m_nextName = 0; | ||
|
||
// Extended constructor to include color | ||
public Particle(Vector2 center, Vector2 direction, float speed, Vector2 size, TimeSpan lifetime, Color initialColor) | ||
{ | ||
this.name = m_nextName++; | ||
this.center = center; | ||
this.direction = direction; | ||
this.speed = speed; | ||
this.size = size; | ||
this.lifetime = lifetime; | ||
this.rotation = 0; | ||
this.color = initialColor; // Initialize color | ||
} | ||
|
||
public bool update(GameTime gameTime) | ||
{ | ||
// Update how long it has been alive | ||
alive += gameTime.ElapsedGameTime; | ||
|
||
// Update its center | ||
center.X += (float)(gameTime.ElapsedGameTime.TotalMilliseconds * speed * direction.X); | ||
center.Y += (float)(gameTime.ElapsedGameTime.TotalMilliseconds * speed * direction.Y); | ||
|
||
// Rotate proportional to its speed | ||
rotation += (speed / 0.5f); | ||
|
||
// Example color fading logic: fade out by reducing the alpha value over time | ||
float lifeFraction = (float)alive.TotalMilliseconds / (float)lifetime.TotalMilliseconds; | ||
color = new Color(color.R, color.G, color.B, (byte)MathHelper.Clamp(255 * (1 - lifeFraction), 0, 255)); | ||
|
||
// Return true if this particle is still alive | ||
return alive < lifetime; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
using Microsoft.Xna.Framework; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace CS5410 | ||
{ | ||
public class ParticleSystem | ||
{ | ||
private Dictionary<long, Particle> m_particles = new Dictionary<long, Particle>(); | ||
public Dictionary<long, Particle>.ValueCollection particles => m_particles.Values; | ||
private MyRandom m_random = new MyRandom(); | ||
|
||
private Vector2 m_center; | ||
private int m_sizeMean; // pixels | ||
private int m_sizeStdDev; // pixels | ||
private float m_speedMean; // pixels per millisecond | ||
private float m_speedStDev; // pixels per millisecond | ||
private float m_lifetimeMean; // milliseconds | ||
private float m_lifetimeStdDev; // milliseconds | ||
|
||
public ParticleSystem(Vector2 center, int sizeMean, int sizeStdDev, float speedMean, float speedStdDev, int lifetimeMean, int lifetimeStdDev) | ||
{ | ||
m_center = center; | ||
m_sizeMean = sizeMean; | ||
m_sizeStdDev = sizeStdDev; | ||
m_speedMean = speedMean; | ||
m_speedStDev = speedStdDev; | ||
m_lifetimeMean = lifetimeMean; | ||
m_lifetimeStdDev = lifetimeStdDev; | ||
} | ||
|
||
public void ShipThrust(Vector2 landerCenter, Vector2 direction, float landerRotation, float landerSize) | ||
{ | ||
Vector2 thrustOffset = new Vector2(0, landerSize / 2); | ||
|
||
Matrix rotationMatrix = Matrix.CreateRotationZ(landerRotation); | ||
thrustOffset = Vector2.Transform(thrustOffset, rotationMatrix); | ||
|
||
Vector2 thrustStartPosition = landerCenter + thrustOffset; | ||
|
||
Color[] particleColors = new Color[] { Color.Red, Color.Orange, Color.Yellow }; | ||
|
||
Vector2[] trianglePoints = new Vector2[] | ||
{ | ||
new Vector2(-0.5f, 1), | ||
new Vector2(0.5f, 1), | ||
new Vector2(0, 0) | ||
}; | ||
|
||
float triangleScale = 5.0f; | ||
|
||
// Scale the triangle points | ||
for (int i = 0; i < trianglePoints.Length; i++) | ||
{ | ||
trianglePoints[i] *= triangleScale; | ||
} | ||
|
||
|
||
for (int i = 0; i < 20; i++) | ||
{ | ||
float size = (float)m_random.nextGaussian(m_sizeMean, m_sizeStdDev); | ||
size *= 4; | ||
|
||
Color initialColor = particleColors[m_random.Next(particleColors.Length)]; | ||
|
||
Vector2 randomPoint = thrustStartPosition + trianglePoints[m_random.Next(trianglePoints.Length)]; | ||
Vector2 targetDirection = randomPoint - thrustStartPosition; | ||
|
||
|
||
float angleVariation = MathHelper.ToRadians(10); | ||
float randomAngle = (float)(m_random.NextDouble() * angleVariation - angleVariation / 2); | ||
targetDirection = Vector2.Transform(targetDirection, Matrix.CreateRotationZ(randomAngle)); | ||
|
||
targetDirection.Y *= 1; | ||
|
||
var particle = new Particle( | ||
thrustStartPosition, | ||
direction + targetDirection * 0.2f, | ||
(float)m_random.nextGaussian(m_speedMean, m_speedStDev) * 0.5f, | ||
new Vector2(size, size), | ||
TimeSpan.FromMilliseconds(m_random.nextGaussian(m_lifetimeMean / 2, m_lifetimeStdDev / 2)), | ||
initialColor | ||
); | ||
m_particles.Add(particle.name, particle); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
||
public void ShipCrash(Vector2 position) | ||
{ | ||
Color[] particleColors = { Color.Red, Color.Orange, Color.Yellow }; | ||
for (int i = 0; i < 500; i++) | ||
{ | ||
float size = (float)m_random.nextGaussian(m_sizeMean, m_sizeStdDev); | ||
Color initialColor = particleColors[m_random.Next(particleColors.Length)]; | ||
Vector2 direction = m_random.nextCircleVector() * 0.5f; | ||
|
||
var particle = new Particle( | ||
position, | ||
direction, // Less spread out direction | ||
(float)m_random.nextGaussian(m_speedMean, m_speedStDev) * 0.3f, // Slower speed for a more condensed effect | ||
new Vector2(size, size), | ||
TimeSpan.FromMilliseconds(m_random.nextGaussian(m_lifetimeMean, m_lifetimeStdDev)), | ||
initialColor | ||
); | ||
m_particles.Add(particle.name, particle); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
public void update(GameTime gameTime) | ||
{ | ||
|
||
List<long> removeMe = new List<long>(); | ||
foreach (var p in m_particles.Values) | ||
{ | ||
if (!p.update(gameTime)) | ||
{ | ||
removeMe.Add(p.name); | ||
} | ||
} | ||
|
||
|
||
foreach (var key in removeMe) | ||
{ | ||
m_particles.Remove(key); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using Microsoft.Xna.Framework; | ||
using Microsoft.Xna.Framework.Content; | ||
using Microsoft.Xna.Framework.Graphics; | ||
|
||
namespace CS5410 | ||
{ | ||
public class ParticleSystemRenderer | ||
{ | ||
private string m_nameParticleContent; | ||
private Texture2D m_texParticle; | ||
|
||
public ParticleSystemRenderer(string nameParticleContent) | ||
{ | ||
m_nameParticleContent = nameParticleContent; | ||
} | ||
|
||
public void LoadContent(ContentManager content) | ||
{ | ||
m_texParticle = content.Load<Texture2D>(m_nameParticleContent); | ||
} | ||
|
||
public void draw(SpriteBatch spriteBatch, ParticleSystem system) | ||
{ | ||
|
||
Vector2 origin = new Vector2(m_texParticle.Width / 2, m_texParticle.Height / 2); | ||
foreach (Particle particle in system.particles) | ||
{ | ||
// Scale the particle size relative to the texture size | ||
Vector2 scale = new Vector2(particle.size.X / m_texParticle.Width, particle.size.Y / m_texParticle.Height); | ||
|
||
spriteBatch.Draw( | ||
m_texParticle, | ||
particle.center, | ||
null, // Full source rectangle | ||
particle.color, // Use particle's color | ||
particle.rotation, | ||
origin, // Centered origin | ||
scale, // Scale to particle size | ||
SpriteEffects.None, | ||
0); | ||
} | ||
|
||
|
||
} | ||
} | ||
} |