Home > TutorialsTechniques
4.3. Particle System - Firework 
In this tutorial you will further use the effects framework of BetaCell; in this case, the effect is a firework.



Click here to go to the forum discussion of this tutorial


 

4.3.1. Prerequisites
default.jpg
Before you start this tutorial make sure that you have:
  • Installed XNA Game Studio 3.1
  • Downloaded the starter project from the downloads section
  • Successfully run the starter project
  • Finish tutorial 4.1.
 

4.3.2. Game Assets 
Game assets [2.3.2] for this tutorial:

 

4.3.3. The using statements
Besides the using statements from the starter project, this tutorial needs the following using statements:

using BetaCell.Environment.Particles;
using BetaCell.Environment.Texture;
using BetaCell.Environment.Particles.Initializers;
using BetaCell.Util.RenderStates;
using BetaCell.Environment.Texture.Feeder;
using BetaCell.Environment.Particles.Parts;


 

4.3.4. Game Attributes 
The attributes that come with the starter project are explained in tutorial section 1.1.4.

For this tutorial we are going to be needing the following attributes:

BCParticleSystem particleSystem;

 

Advertisement
 

4.3.5. The Initialize method 

The only new part of the initialize method is the use of a different initializer:

BCFixedInitializer initializer = new BCFixedInitializer(
    new Vector4(0, 0, 3, 1),
    3.5f, new Color(192, 192, 192, 64),
    100, 200,
    0.01f, 0.1f,
    new Vector4(-2.5f, 5, -2.5f, 0), new Vector4(2.5f, 15, 2.5f, 0)
);

The parameters are:
  1. The initial position of the particles
  2. The time in seconds that a particle will live
  3. The initial color of the particles
  4. The minimum size in pixels of a particle
  5. The maximum size in pixels of a particle
  6. The minimum custom
  7. The maximum custom
  8. The minimum initial vector velocity of a particle.
  9. The maximum initial vector velocity of a particle.

 

4.3.6. The Draw method
The method disables the cull mode, draws the particle system and enables back the cull:

CullMode currentCullMode = device.RenderState.CullMode;
device.RenderState.CullMode = CullMode.None;
particleSystem.Draw(gameTime);
device.RenderState.CullMode = currentCullMode;

 

4.3.7. Conclusion
Look how with a very little change, you achieved a different particle effect, try adding other parts to see the behavior.

Click here to go to the forum discussion of this tutorial
 
 

Advertisement
 

4.3.8. Complete source code
using System;
using System.Collections.Generic;
using System.Threading;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using BetaCell.Debug;
using BetaCell.Util.GlobalInfo.Content;
using BetaCell.Environment.Camera;
using BetaCell.Util.GlobalInfo;

using BetaCell.Environment.Particles;
using BetaCell.Environment.Texture;
using BetaCell.Environment.Particles.Initializers;
using BetaCell.Util.RenderStates;
using BetaCell.Environment.Texture.Feeder;
using BetaCell.Environment.Particles.Parts;

namespace Starter
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        //Game attributes
        GraphicsDeviceManager graphics;
        GraphicsDevice device;
        ContentManager content;

        BCFirstPersonHumanCamera camera;
        //end game attributes

        BCParticleSystem particleSystem;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8;
            content = new ContentManager(Services);

#if(XBOX360)
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 768;
#else
            graphics.PreferredBackBufferWidth = 852;
            graphics.PreferredBackBufferHeight = 480;
#endif
        }

        protected override void Initialize()
        {
            device = graphics.GraphicsDevice;
            BCLogger.instance.init(device, content);
            BCInitializationManager.initialize(content);

            OnActivated(null, null);

            BCLogger.instance.message.color = Color.White;

            //-----
            //Particle system
            //-----

            BCMemoryTextureStrategy spark = new BCMemoryTextureStrategy(
                content.Load<Texture2D>("Content/gameAssets/spark"));

            BCFixedInitializer initializer = new BCFixedInitializer(
                new Vector4(0, 0, 3, 1),
                4f, new Color(192, 192, 192, 64),
                100, 200,
                0.01f, 0.1f,
                new Vector4(-1f, 2.5f, -1f, 0), new Vector4(1f, 7.5f, 1f, 0)
            );

            particleSystem = new BCParticleSystem(
                device,
                spark,
                0,
                null,
                4000,
                0.001f,
                "Particles.Base",
                initializer,
                new BCAdditiveAlphaRenderStrategy()
            );

            BCSampler sampler = new BCSampler(
                "LINEAR", "LINEAR", "POINT", "4",
                "CLAMP", "CLAMP", "0xffffffff");

            BCParticleAccelerationPart acceleration = new BCParticleAccelerationPart(
                "Particles.Parts.Acceleration", new Vector4(0, -1.8f, 0, 0));

            BCParticleDistanceResizePart resizeDistance =
                new BCParticleDistanceResizePart("Particles.Parts.DistanceResize", 800);
            resizeDistance.linearDecimator = 1;

            BCParticleFade fade = new BCParticleFade("Particles.Parts.Fade");

            particleSystem.initEffect(device, "Shader.Texture.Sprite", sampler,
                acceleration, resizeDistance, fade);

            base.Initialize();
        }

        protected override void OnActivated(object sender, EventArgs args)
        {
            buildViewMatrix();
            base.OnActivated(sender, args);
        }

        void buildViewMatrix()
        {
            Vector3 pos = new Vector3(0, 4, -10);
            Vector3 look = new Vector3(0, 0, 1);
            look.Normalize();

            camera = new BCFirstPersonHumanCamera(look, pos,
                MathHelper.PiOver4,
                (float)this.Window.ClientBounds.Width / (float)this.Window.ClientBounds.Height,
                1f, 200);

            BCGlobalInfo.instance.setMatrix(
                BCGlobalInfo.VIEW_INDEX,
                camera.getViewMatrix(-1)
            );

            BCGlobalInfo.instance.setMatrix(
                BCGlobalInfo.PROJECTION_INDEX,
                camera.getProjectionMatrix(-1)
            );
        }

        protected override void Update(GameTime gameTime)
        {
            particleSystem.update((float)gameTime.TotalGameTime.TotalSeconds);
            moveCamera(gameTime);
        }

        private void moveCamera(GameTime gameTime)
        {

            float df = 0;
            float ds = 0;
            float dy = 0;
            float pitch = 0;
            float angleY = 0;

            float speed = 5f;
#if (XBOX360)
            GamePadState gamepad = GamePad.GetState(PlayerIndex.One);

            df = gamepad.ThumbSticks.Left.Y;
            ds = gamepad.ThumbSticks.Left.X;
            pitch = -gamepad.ThumbSticks.Right.Y * 0.05f;
            angleY = gamepad.ThumbSticks.Right.X * 0.05f;

            if (gamepad.IsButtonDown(Buttons.RightShoulder))
            {
                dy += 0.25f;
            }
            if (gamepad.IsButtonDown(Buttons.LeftShoulder))
            {
                dy -= 0.25f;
            }

            speed = new Vector3(df, ds, dy).Length() * 10;
#else

            KeyboardState keys = Keyboard.GetState();
            MouseState mouse = Mouse.GetState();

            if (keys.IsKeyDown(Keys.W))
            {
                df += 1;
            }
            if (keys.IsKeyDown(Keys.S))
            {
                df -= 1;
            }
            if (keys.IsKeyDown(Keys.D))
            {
                ds += 1;
            }
            if (keys.IsKeyDown(Keys.A))
            {
                ds -= 1;
            }
            if (keys.IsKeyDown(Keys.Q))
            {
                dy += 1;
            }
            if (keys.IsKeyDown(Keys.E))
            {
                dy -= 1;
            }
            speed = 5f;
            if (keys.IsKeyDown(Keys.LeftControl))
            {
                speed = 10f;
            }

            angleY = ((float)this.Window.ClientBounds.Width / 2.0f - (float)mouse.X) * -0.05f;
            pitch = ((float)this.Window.ClientBounds.Height / 2.0f - (float)mouse.Y) * -0.05f;

            Mouse.SetPosition(this.Window.ClientBounds.Width / 2, this.Window.ClientBounds.Height / 2);

#endif
            camera.update(df, dy, ds, pitch, angleY, speed, (float)gameTime.ElapsedGameTime.TotalSeconds);

            BCGlobalInfo.instance.setMatrix(BCGlobalInfo.VIEW_INDEX, camera.getViewMatrix(-1));
        }

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

            CullMode currentCullMode = device.RenderState.CullMode;
            device.RenderState.CullMode = CullMode.None;
            particleSystem.Draw(gameTime);
            device.RenderState.CullMode = currentCullMode;

            BCLogger.instance.printFPS(gameTime);
            BCLogger.instance.flush();
            base.Draw(gameTime);
        }
    }
}