123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- //-----------------------------------------------------------------------------
- // ParticleSystem.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Content;
- using Microsoft.Xna.Framework.Graphics;
- namespace AlienGameSample
- {
- /// <summary>
- /// A relatively simple particle system. We recycle particles instead of creating
- /// and destroying them as we need more. "Effects" are created via factory methods
- /// on ParticleSystem, rather than a data driven model due to the relatively low
- /// number of effects.
- /// </summary>
- public class ParticleSystem
- {
- Random random;
- Texture2D tank_tire;
- Texture2D tank_top;
- Texture2D fire;
- Texture2D smoke;
- SpriteBatch spriteBatch;
- List<Particle> particles;
- public ParticleSystem(ContentManager content, SpriteBatch spriteBatch)
- {
- random = new Random();
- particles = new List<Particle>();
- this.spriteBatch = spriteBatch;
- tank_tire = content.Load<Texture2D>("tank_tire");
- tank_top = content.Load<Texture2D>("tank_top");
- fire = content.Load<Texture2D>("fire");
- smoke = content.Load<Texture2D>("smoke");
- }
- /// <summary>
- /// Update all active particles.
- /// </summary>
- /// <param name="elapsed">The amount of time elapsed since last Update.</param>
- public void Update(float elapsed)
- {
- for (int i = 0; i < particles.Count; ++i)
- {
- particles[i].Life -= elapsed;
- if (particles[i].Life <= 0.0f)
- {
- continue;
- }
- particles[i].Position += particles[i].Velocity * elapsed;
- particles[i].Rotation += particles[i].RotationRate * elapsed;
- particles[i].Alpha += particles[i].AlphaRate * elapsed;
- particles[i].Scale += particles[i].ScaleRate * elapsed;
- if (particles[i].Alpha <= 0.0f)
- particles[i].Alpha = 0.0f;
- }
- }
- /// <summary>
- /// Draws the particles.
- /// </summary>
- public void Draw()
- {
- for (int i = 0; i < particles.Count; ++i)
- {
- Particle p = particles[i];
- if (p.Life <= 0.0f)
- continue;
- float alphaF = 255.0f * p.Alpha;
- if (alphaF < 0.0f)
- alphaF = 0.0f;
- if (alphaF > 255.0f)
- alphaF = 255.0f;
- spriteBatch.Draw(p.Texture, p.Position, null, new Color(p.Color.R, p.Color.G, p.Color.B, (byte)alphaF), p.Rotation, new Vector2(p.Texture.Width / 2, p.Texture.Height / 2), p.Scale, SpriteEffects.None, 0.0f);
- }
- }
- /// <summary>
- /// Creats a particle, preferring to reuse a dead one in the particles list
- /// before creating a new one.
- /// </summary>
- /// <returns></returns>
- Particle CreateParticle()
- {
- Particle p = null;
- for (int i = 0; i < particles.Count; ++i)
- {
- if (particles[i].Life <= 0.0f)
- {
- p = particles[i];
- break;
- }
- }
- if (p == null)
- {
- p = new Particle();
- particles.Add(p);
- }
- p.Color = Color.White;
- return p;
- }
- /// <summary>
- /// Creats the effect for when an alien dies.
- /// </summary>
- /// <param name="position">Where on the screen to create the effect.</param>
- public void CreateAlienExplosion(Vector2 position)
- {
- Particle p = null;
- for (int i = 0; i < 8; ++i)
- {
- p = CreateParticle();
- p.Position = position;
- p.RotationRate = -6.0f + 12.0f * (float)random.NextDouble();
- p.Scale = 0.5f;
- p.ScaleRate = 0.25f;// *(float)random.NextDouble();
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Velocity.X = -32.0f + 64.0f * (float)random.NextDouble();
- p.Velocity.Y = -32.0f + 64.0f * (float)random.NextDouble();
- p.Texture = smoke;
- p.Life = 2.0f;
- }
- for (int i = 0; i < 3; ++i)
- {
- p = CreateParticle();
- p.Position = position;
- p.Position.X += -8.0f + 16.0f * (float)random.NextDouble();
- p.Position.Y += -8.0f + 16.0f * (float)random.NextDouble();
- p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
- p.Scale = 0.25f;
- p.ScaleRate = 1.0f;// *(float)random.NextDouble();
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Velocity = Vector2.Zero;
- p.Texture = fire;
- p.Life = 2.0f;
- }
- }
- /// <summary>
- /// Creats the effect for when the player dies.
- /// </summary>
- /// <param name="position">Where on the screen to create the effect.</param>
- public void CreatePlayerExplosion(Vector2 position)
- {
- Particle p = null;
- for (int i = 0; i < 16; ++i)
- {
- p = CreateParticle();
- p.Position = position;
- p.RotationRate = -6.0f + 12.0f * (float)random.NextDouble();
- p.Scale = 0.5f;
- p.ScaleRate = 0.25f;// *(float)random.NextDouble();
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Velocity.X = -32.0f + 64.0f * (float)random.NextDouble();
- p.Velocity.Y = -32.0f + -48.0f * (float)random.NextDouble();
- p.Texture = smoke;
- p.Life = 2.0f;
- }
- p = CreateParticle();
- p.Texture = tank_tire;
- p.Position = position;
- p.Scale = 1.0f;
- p.ScaleRate = 0.0f;
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Life = 2.0f;
- p.RotationRate = 0.5f;
- p.Rotation = 0.0f;
- p.Velocity = new Vector2(40.0f, -75.0f);
- p = CreateParticle();
- p.Texture = tank_tire;
- p.Position = position;
- p.Scale = 1.0f;
- p.ScaleRate = 0.0f;
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Life = 2.0f;
- p.RotationRate = 0.5f;
- p.Rotation = 0.0f;
- p.Velocity = new Vector2(-45.0f, -90.0f);
- p = CreateParticle();
- p.Texture = tank_top;
- p.Position = position;
- p.Scale = 1.0f;
- p.ScaleRate = 0.0f;
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Life = 2.0f;
- p.RotationRate = 2.5f;
- p.Rotation = 0.0f;
- p.Velocity = new Vector2(0.0f, -60.0f);
- for (int i = 0; i < 8; ++i)
- {
- p = CreateParticle();
- p.Position = position;
- p.Position.X += -16.0f + 32.0f * (float)random.NextDouble();
- p.Position.Y += -16.0f + 32.0f * (float)random.NextDouble();
- p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
- p.Scale = 0.25f;
- p.ScaleRate = 1.0f;// *(float)random.NextDouble();
- p.Alpha = 2.0f;
- p.AlphaRate = -1.0f;
- p.Velocity.X = -4.0f + 8.0f * (float)random.NextDouble();
- p.Velocity.Y = -4.0f + -8.0f * (float)random.NextDouble();
- p.Texture = fire;
- p.Life = 2.0f;
- }
- }
- /// <summary>
- /// Creats the mud/dust effect when the player moves.
- /// </summary>
- /// <param name="position">Where on the screen to create the effect.</param>
- public void CreatePlayerDust(Player player)
- {
- for (int i = 0; i < 2; ++i)
- {
- Particle p = CreateParticle();
- p.Texture = smoke;
- p.Color = new Color(125, 108, 43);
- p.Position.X = player.Position.X + player.Width * (float)random.NextDouble();
- p.Position.Y = player.Position.Y + player.Height - 3.0f * (float)random.NextDouble();
- p.Alpha = 1.0f;
- p.AlphaRate = -2.0f;
- p.Life = 0.5f;
- p.Rotation = 0.0f;
- p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
- p.Scale = 0.25f;
- p.ScaleRate = 0.5f;
- p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();
- p.Velocity.Y = -8 + 4.0f * (float)random.NextDouble();
- }
- }
- /// <summary>
- /// Creats the effect for when the player fires a bullet.
- /// </summary>
- /// <param name="position">Where on the screen to create the effect.</param>
- public void CreatePlayerFireSmoke(Player player)
- {
- for (int i = 0; i < 8; ++i)
- {
- Particle p = CreateParticle();
- p.Texture = smoke;
- p.Color = Color.White;
- p.Position.X = player.Position.X + player.Width / 2;
- p.Position.Y = player.Position.Y;
- p.Alpha = 1.0f;
- p.AlphaRate = -1.0f;
- p.Life = 1.0f;
- p.Rotation = 0.0f;
- p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
- p.Scale = 0.25f;
- p.ScaleRate = 0.25f;
- p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();
- p.Velocity.Y = -16.0f + -32.0f * (float)random.NextDouble();
- }
- }
- }
- /// <summary>
- /// A basic particle. Since this is strictly a data class, I decided to not go
- /// the full property route and used public fields instead.
- /// </summary>
- public class Particle
- {
- public Vector2 Position;
- public Vector2 Velocity;
- public Texture2D Texture;
- public float RotationRate;
- public float Rotation;
- public float Life;
- public float AlphaRate;
- public float Alpha;
- public float ScaleRate;
- public float Scale;
- public Color Color = Color.White;
- }
- }
|