Tuesday 31 July 2012

A 2D Particle System

So, Dave was having some issue with creating a particle system for his game, so thought I could come up with a game specific particle system. I say game specific, because it is just that, the system is usable for the game I/you write it for, it’s not going to sit in an engine and be used, though you could with a few tweaks.

In fact, there are a tone of optimizations you could do with this, but for this sample it does enough.

My idea was, to have an emitter manager that was a registered game service, this service could then be accessed by all your game components and each component could call and place emitters as and when they want/need them. Also, you could have emitters call other emitters if you need to, in the sample, you will see I have done this for the explosions, first an explosion emitter is called and when it is halfway through it’s cycle, it calls a smoke bomb emitter.

You may notice, this sample has a bit more than the emitter code in it, I got a bit carried away and almost wrote a game using it lol, if you like feel free to finish off :)

ParticleEmitterService

First thing we will look at is the emitter service, it is derived from the DrawableGameComponent that is intrinsic to XNA, it has two lists of IParticleEmitter, this is an interface I have created to describe a particle emitter, using this interface means you can write a totally new emitter and as long as it implements this interface, the emitter service can use it. The first list is the current list of emitters in use, I then have another list that is for emitters that are being created while we are in the Update loop, we can’t action these until we are out off the loop, so I put them in a queue to be added later.

    public class ParticleEmitterService : DrawableGameComponent
    {
        public List<IParticleEmitter> Emitters = new List<IParticleEmitter>();
        List<IParticleEmitter> emitterQue = new List<IParticleEmitter>();

        bool Updating = false;

We then have the constructor (ctor) for the class, and in here I get it to register it’s self as a service with the Game instance and add it’s self to the Game.Components.

        public ParticleEmitterService(Game game)
            : base(game)
        {
            // Automaticaly register myself as a service
            game.Services.AddService(this.GetType(),this);

            // Put myself in the component list
            game.Components.Add(this);
        }

I then have an add emitter method so that game entities can invoke an emitter, as you will see this method checks if we are in the update method and if we are adds the new emitter to the queue. I created an enum so you could just say what pre baked emitter you want, you could just pass the emitter instance in rather than do it this way, but for this sample this makes it a bit simpler.

        public void AddEmitter(EmitterType emitterType, Vector2 position, IGameEntity entity = null, Vector2? entityOffset = null)
        {
            IParticleEmitter emitter = null;

            if (entityOffset == null)
                entityOffset = Vector2.Zero;

            bool added = false;
            switch (emitterType)
            {
                case EmitterType.Explosion:
                    emitter = new ExplosionEmitter(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = true };
                    added = true;
                    break;
                case EmitterType.Fire:
                    break;
                case EmitterType.SmokeBomb:
                    emitter = new SmokeBombEmitter(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = true };
                    added = true;
                    break;
                case EmitterType.SmokeTail:
                    emitter = new SmokeTrailEmitter(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = true };
                    added = true;
                    break;
            }

            if(added)
                emitter.Initialize();

            if (Updating)
                emitterQue.Add(emitter);
            else
                Emitters.Add(emitter);
        }

In our update method we check to see if we have any emitters in the queue, and if we do, we merge them with the main emitter list and clear the queue out. Then set the Updating flag to true, so if any are added while we are in here they are added to the queue. Then we go through our list, and call there Update methods, and if they are no longer alive, add them to the list to be removed from the emitter list. Then loop through and remove the emitters that are no no longer alive and call there Die method, in some emitters, you may want to do some other stuff once the emitter has completed. We the set the Updating flag to false.

        public override void Update(GameTime gameTime)
        {
            List<IParticleEmitter> removeList = new List<IParticleEmitter>();

            // Update from que if need be.
            foreach (IParticleEmitter emitter in emitterQue)
            {
                Emitters.Add(emitter);
            }
            emitterQue.Clear();

            Updating = true;
            foreach (IParticleEmitter emitter in Emitters)
            {
                
                if (!emitter.Alive)
                    removeList.Add(emitter);

                if(emitter.Enabled)
                    emitter.Update(gameTime);
            }

            foreach (IParticleEmitter emitter in removeList)
            {
                emitter.Die();
                Emitters.Remove(emitter);
            }
            Updating = false;
        }

The draw call is much simpler, just iterate through our emitters and make there draw calls.

        public override void Draw(GameTime gameTime)
        {
            foreach (IParticleEmitter emitter in Emitters)
            {
                if(emitter.Visible)
                    emitter.Draw(gameTime);
            }
        }

 

Interfaces

In the sample I have two interfaces, the aforementioned IParticleEmitter interface and the IGameEntity interface. I created the latter so I could bind an emitter to a screen object, so if you look at the clip, you can see the smoke trail is fixed to the ship, where ever the ship goes, the smoke trail follows.

IParticleEmitter
    public interface IParticleEmitter : IGameEntity
    {
        SpriteBatch SpriteBatch { get; }

        ParticleEmitterService ParticleEmitter { get; }

        BlendState ParticleBlendState { get; set; }

        IGameEntity GameEntity { get; set; }
        Vector2 EnityOffset { get; set; }

        Vector2[] particles { get; set; }
        float[] scaleParticle { get; set; }
        float[] rotationParticle { get; set; }
        bool[] activeParticle { get; set; }

        Color Color { get; set; }

        Texture2D texture { get; set; }

        int ParticleCount { get; }

        bool Alive { get; set; }

        void Die();
    }

As you can see, we have a few elements in there, but firstly we implement IGamEntity, here, why? Well you might want to hang an emitter off an emitter, so, a smoke trail off a fire ball for example, also, my IGameEntity also gives us other data structures, like position, scale, rotation, as well as bounds data (not implemented in here for the particle system) and a Docollision method (again, not for particles here)

IGameEntity
    public interface IGameEntity : IGameComponent, IUpdateable, IDrawable
    {
        Vector2 Position { get; set; }
        Vector2 Origin { get; set; }

        float Scale { get; set; }
        float Rotation { get; set; }

        Rectangle bounds { get; }

        bool DoCollision(IGameEntity entity);
    }

This interface has all the stuff we need for our game entities.

Actually looking back over the interfaces, we could cull out a lot of these items as they are not used in the sample by implementing the interfaces, but I have kept them in here as you may need them later on (maybe).

Emitters

So, what do the emitters look like? Well to make life a bit more easier, I decided to use a base class that the emitters can then derive from, this base class implements the IParticleEmitter interface, so all you need to do to create a new emitter is to derive from this base class and away you go.

EmitterBase

As you might expect, EmitterBase implements our interfaces, the ctor sets up our default values

        public EmitterBase(Game game, string TextureAsset)
            : base(game)
        {
            textureAsset = TextureAsset;

            Position = Vector2.Zero;
            Origin = Vector2.Zero;
            Scale = 1f;
            Rotation = 0;

            ParticleBlendState = BlendState.Additive;

            Color = Color.White;
        }

Initialise, well intializes the lists we need to implement the emitter

        public override void Initialize()
        {
            particles = new Vector2[ParticleCount];
            scaleParticle = new float[ParticleCount];
            rotationParticle = new float[ParticleCount];
            activeParticle = new bool[ParticleCount];

            texture = Game.Content.Load<Texture2D>(textureAsset);
            Origin = new Vector2(texture.Width / 2, texture.Height / 2);

            for (int p = 0; p < ParticleCount; p++)
            {
                rotationParticle[p] = 0;
                particles[p] = Vector2.Zero;
                scaleParticle[p] = Scale;
            }
        }

Our update method is only of use if we have given the emitter an IGameEntity to bind to, and if it does, endures that we stick to that entity.

        public override void Update(GameTime gameTime)
        {
            if (GameEntity != null)
            {
                Rotation = GameEntity.Rotation;
                Position = GameEntity.Position + EnityOffset;
            }
        }

Our draw method again, simply draws the particles where we want them

        public override void Draw(GameTime gameTime)
        {
            SpriteBatch.Begin(SpriteSortMode.Deferred, ParticleBlendState);

            for (int p = 0; p < ParticleCount; p++)
            {
                if (activeParticle[p])
                    SpriteBatch.Draw(texture, particles[p], null, Color, rotationParticle[p], Origin, scaleParticle[p], SpriteEffects.None, 0);
            }

            SpriteBatch.End();
        }

Our DoCollision  and Die methods are just place holders for the base class, but we make sure they are virtual so they can be overriden later.

        public virtual bool DoCollision(IGameEntity entity)
        {
            return false;
        }

        public virtual void Die()
        {

        }

So, that’s the basic structure, but what does an example emitter look like? Lets have a look at the SmokeTrail emitter.

SmokeTrailEmitter

First off, we derive from EmitterBase, this way we have all the intrinsic goodness from that base class for our emitter, and it is then by default a IParticleEmitter and an IGameEntity.

In the ctor, we set the texture to be used, the number of particles and the scale, in the Initialize method, we ensure our first particle is active.

    public class SmokeTrailEmitter : EmitterBase
    {
        public SmokeTrailEmitter(Game game)
            : base(game, "Textures/Particles/Smoke")
        {
            particleCount = 10;
            Scale = .1f;
        }

        public override void Initialize()
        {
            base.Initialize();
            activeParticle[0] = true;
        }

Then all we have to do, is write the Update method, in here, we are looping through all the particles in the list, if they are active we move them down the screen, and increase there scale a little and rotate them a bit. We also measure the distance from the emitter and if greater (in this case) than 150 pixels, we deactivate it.

        public override void Update(GameTime gameTime)
        {
            // set particle positions.
            for (int p = 0; p < ParticleCount; p++)
            {
                if (activeParticle[p])
                {
                    rotationParticle[p] -= (p + 1) / ParticleCount;
                    particles[p].Y += 8f;                    
                    scaleParticle[p] += .015f;
                    float dist = Vector2.Distance(Position, particles[p]);

                    if (dist > 150)
                        activeParticle[p] = false;
                }

If the particle is not active, we then see if we need to activate it, so we set it’s position to that of the emitter, randomly move it either left or right a bit so we get a bobbly smoke effect and set it’s scale to the starting scale value. We then compare it’s distance from the last particle and if greater that 25 make it active.

                else
                {
                    particles[p] = Position;
                    particles[p].X += MathHelper.Lerp(-5, 5, (float)rnd.NextDouble());

                    scaleParticle[p] = Scale;
                    int nextP = p - 1;

                    if (p == 0)
                    {
                        nextP = ParticleCount - 1;
                    }

                    float dist = Vector2.Distance(particles[nextP], particles[p]);
                    if (dist > 25)
                        activeParticle[p] = true;
                }
            }
            base.Update(gameTime);
        }

I know, not the most awesome particle emitter, but it’s showing you how you can create you own emitters, take a look at the ExplosionEmitter’s Update method, this gives a totally different emitter result

        public override void Update(GameTime gameTime)
        {
            for (int p = 0; p < ParticleCount; p++)
            {
                //particles[p] = Position;
                rotationParticle[p] += (ParticleCount / (p+1)) * .1f;
                if (blowOut)
                    Scale += .0025f;
                else
                {
                    a -= .005f;
                    if (a <= 0)
                        a = 0;
                    
                    Color = new Color(Color.R, Color.G, Color.B, (byte)(a * 255));

                    Scale -= .0025f;
                }

                if (Scale > .5f)
                {
                    Scale = .5f;
                    blowOut = !blowOut;
                    ParticleEmitter.AddEmitter(EmitterType.SmokeBomb, Position);
                }
                scaleParticle[p] = Scale;
            }

            if (Scale <= 0)
                Alive = false;
            
            
            base.Update(gameTime);
        }

And now the one for the SmokeBombEmitter, again totally different results.

        public override void Update(GameTime gameTime)
        {
            for (int p = 0; p < ParticleCount; p++)
            {
                //particles[p] = Position;
                rotationParticle[p] += (ParticleCount / (p + 1)) * .1f;
                Scale += .0025f;
                a -= .0025f;
                if (a <= 0)
                    a = 0;
                scaleParticle[p] = Scale;
                Color = new Color(Color.R, Color.G, Color.B, (byte)(a*255));
            }

            if (a <= 0)
                Alive = false;

            base.Update(gameTime);
        }

Hope you find this useful, you can get all the source code for this here.

Also, the project uses a specific font, you can download it here, or swap it for one you have.

As ever C&C welcome.

Wednesday 25 July 2012

Line Intersection – y = mx + c

So, a twitter conversation started up with Dave Voyles, he wanted to be able to find the exact point that two rectangles collided with each other, some suggestions got thrown about, but I thought one way to do it would be to use the line equation,

image

This equation is used to represent a line, the x and y co-ords are the possible points along this line, m in the gradient or slope of the line and the c is where the line crosses through the y axis on a graph and is known as the y intercept.

So I thought, you could build 4 of these lines from your rectangles, then using this equation you can find exactly where the line(s) intersect.

I am not going to cover all the math here, but what I am doing here is first finding the slope and y intercept of the two lines, we then see if both lines are vertical or horizontal, if both lines are then it’s pretty simple to solve, if not, then we have to re calculate the lope and the y intercept.

That done we can then check to see if our two equations add up,so I solve for y in both cases, if they are equal, then we just need to make sure that our x value lies on both the lines based on the line min and max values….and, well that’s about it.

As I have said before, I am probably sub GCSE math, so a lot of this could well be all bum, but it works, please point and laugh out loud at my crap math but please give your reasons for pointing and laughing, that way we all learn from my mistakes :)

I wrote this class a long time ago to, and had to dig the source out from my HDD to post it here.

Here are some pics of the code in action, we have 2 lines, first image is with no intersection

image

I can then rotate the green line round so that it intersects, here are a few images of the lines intersecting, the red dot (if you can see it) is the exact point of intersection.

image

image

image

I made a mod to my original code so if the lines are both vertical or both horizontal it gets an intersection point based on the two inner points and puts it in the middle, like this

image

And  this

image

You can download the sample code for this here.

You can control the green line with the arrow keys to move it about, the keys Q and Z to scale it’s length, as well as E and C to rotate it.

For more help and better explanation of the y = mx + c equation, google it, there are loads of math resources out there.

Wednesday 11 July 2012

Volumetric Clouds in XNA 4.0

As mentioned in the last post and the comments before that, I got asked to port my old XNA 3.x volumetric clouds over to XNA 4.0, and that’s just what I have done, but with a few changes.
The first is I am using instancing, if you don’t know what instancing is, it’s a way we can pass one set of geometry to the graphic card, but have it render lots and lots of instances of that geometry. So, in the case of our clouds, we render wisps' that are render on a quad or billboard, this billboard is just verts, so as far as the vertex buffer goes, it just holds these 4 verts, on another channel we send the graphics card a list of transforms, these transforms (or world matrix’s) represent and instance to be rendered, so, if we send ten transforms, then 10 billboards will be rendered.
You can find my archived post on the original code base here.
So, that’s quite a change from the old implementation, in the earlier version I had Point Sprites (never a good idea) and billboards, and I would chain them up into a single draw call, so the vertex buffer would be the number of wisps multiplied by four, one for each vert in the quad. It gave a good result, and looked like this
You can see in the clip, it’s a bit laggy, but to be fair it was running on a very old and crappy laptop.
I also changed the shader a little, as I had to anyway to get the instancing to work, but also to get a better fade as the camera got close to the cloud, before as you approached the cloud, it would fade out, but as I was doing this in the vertex shader, if it was a big billboard you would see the billboard rotate and  then start to fade. I am still doing this check in the vertex shader, but I am also now doing it in the pixel shader, it now fades the cloud out much better and reduces the visibility of the twisting billboard artifact on large billboards.
This is what it now looks like
So, here is the code for the clouds in XNA 4.0
Next post ill expand on instancing a bit more and show how I used it to render 1 million particles :)
REMEMBER: DO NOT COMERCIALY USE THE CLOUD TEXTURE IN THE ZIP AS IT IS PROPERTY OF MS!
Just so you know and don’t get your self stung, I have put this comment in the code where ever it is referenced.
            //////////////////////////////////////////////////////////////////
            // REMEMBER THE CloudSpriteSheetOrg texture is property of MS   //
            // Do not comercialy use this texture!                          //
            //////////////////////////////////////////////////////////////////

Tuesday 10 July 2012

Volumetric Clouds in XNA 4.0



Anne-Lise Pasch asked me to update the cloud sample I did way back in XNA 4.0, so this is my progress so far, hoping to write the blog post this week, if I have time :)
What I love about this is each and every scene is done with a single draw call :)

As ever, comments are welcome :D