2D Particle Explosion
- by TheBroodian
I'm developing a 2D action game, and in said game I've given my primary character an ability he can use to throw a fireball. I'm trying to design an effect so that when said fireball collides (be it with terrain or with an enemy) that the fireball will explode. For the explosion effect I've created a particle that once placed into game space will follow random, yet autonomic behavior based on random variables.
Here is my question: When I generate my explosion (essentially 90 of these particles) I get one of two behaviors,
1) They are all generated with the same random variables, and don't resemble an explosion at all, more like a large mass of clumped sprites that all follow the same randomly generated path.
2) If I assign each particle a unique seed to its random number generator, they are a little bit -more- spread out, yet clumping is still visible (they seem to fork out into 3 different directions)
Does anybody have any tips for producing particle-based 2D explosions? I'll include the code for my particle and the event I'm generating them in.
Fire particle class:
public FireParticle(xTile.Dimensions.Location StartLocation, ContentManager content)
{
worldLocation = StartLocation;
fireParticleAnimation = new FireParticleAnimation(content);
random = new Random();
int rightorleft = random.Next(0, 3);
int upordown = random.Next(1, 3);
int xVelocity = random.Next(0, 101);
int yVelocity = random.Next(0, 101);
Vector2 tempVector2 = new Vector2(0,0);
if (rightorleft == 1)
{
tempVector2 = new Vector2(xVelocity, tempVector2.Y);
}
else if (rightorleft == 2)
{
tempVector2 = new Vector2(-xVelocity, tempVector2.Y);
}
if (upordown == 1)
{
tempVector2 = new Vector2(tempVector2.X, -yVelocity);
}
else if (upordown == 2)
{
tempVector2 = new Vector2(tempVector2.X, yVelocity);
}
velocity = tempVector2;
scale = random.Next(1, 11);
upwardForce = -10;
dead = false;
}
public FireParticle(xTile.Dimensions.Location StartLocation, ContentManager content, int seed)
{
worldLocation = StartLocation;
fireParticleAnimation = new FireParticleAnimation(content);
random = new Random(seed);
int rightorleft = random.Next(0, 3);
int upordown = random.Next(1, 3);
int xVelocity = random.Next(0, 101);
int yVelocity = random.Next(0, 101);
Vector2 tempVector2 = new Vector2(0, 0);
if (rightorleft == 1)
{
tempVector2 = new Vector2(xVelocity, tempVector2.Y);
}
else if (rightorleft == 2)
{
tempVector2 = new Vector2(-xVelocity, tempVector2.Y);
}
if (upordown == 1)
{
tempVector2 = new Vector2(tempVector2.X, -yVelocity);
}
else if (upordown == 2)
{
tempVector2 = new Vector2(tempVector2.X, yVelocity);
}
velocity = tempVector2;
scale = random.Next(1, 11);
upwardForce = -10;
dead = false;
}
#endregion
#region Update and Draw
public void Update(GameTime gameTime)
{
elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
fireParticleAnimation.Update(gameTime);
Vector2 moveAmount = velocity * elapsed;
xTile.Dimensions.Location newPosition = new xTile.Dimensions.Location(worldLocation.X + (int)moveAmount.X, worldLocation.Y + (int)moveAmount.Y);
worldLocation = newPosition;
velocity.Y += upwardForce;
if (fireParticleAnimation.finishedPlaying)
{
dead = true;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(
fireParticleAnimation.image.Image,
new Rectangle((int)drawLocation.X, (int)drawLocation.Y, scale, scale),
fireParticleAnimation.image.SizeAndsource,
Color.White * fireParticleAnimation.image.Alpha);
}
Fireball explosion event:
public override void Update(GameTime gameTime)
{
if (enabled)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
foreach (Heart_of_Fire.World_Objects.Particles.FireParticle particle in explosionParticles.ToList())
{
particle.Update(gameTime);
if (particle.Dead)
{
explosionParticles.Remove(particle);
}
}
collisionRectangle = new Microsoft.Xna.Framework.Rectangle((int)wrldPstn.X, (int)wrldPstn.Y, 5, 5);
explosionCheck = exploded;
if (!exploded)
{
coreGraphic.Update(gameTime);
tailGraphic.Update(gameTime);
Vector2 moveAmount = velocity * elapsed;
moveAmount = horizontalCollision(moveAmount, layer);
moveAmount = verticalCollision(moveAmount, layer);
Vector2 newPosition = new Vector2(wrldPstn.X + moveAmount.X, wrldPstn.Y + moveAmount.Y);
if (hasCollidedHorizontally || hasCollidedVertically)
{
exploded = true;
}
wrldPstn = newPosition;
worldLocation = new xTile.Dimensions.Location((int)wrldPstn.X, (int)wrldPstn.Y);
}
if (explosionCheck != exploded)
{
for (int i = 0; i < 90; i++)
{
explosionParticles.Add(new World_Objects.Particles.FireParticle(
new Location(
collisionRectangle.X + random.Next(0, 6),
collisionRectangle.Y + random.Next(0, 6)),
contentMgr));
}
}
if (exploded && explosionParticles.Count() == 0)
{
//enabled = false;
}
}
}