Friday, April 18, 2014

13: Muzzle Flash and Blood Splatter Effects



       This is a video demonstration of the muzzle flash and blood splatter effect I recently got working in the game. The game engine is built upon the XNA 4.0 Framework and MonoGame. I have also attached the temporary gun model to the sample marine character. The blood splatter and muzzle flash effect is an animated billboard. A billboard is simply a 2D sprite rendered in 3D space. This is a fake way of rendering complex effects and models. If the camera moves to view the blood splatter effects' sides as of now, it can no longer be read. Now I just have to rotate the animated blood splatter sprites so that they will always face toward the camera. This is so the blood splatter effect will appear fully 3D. I also got the marine character's weapon model attached. I will explain more about how I was able to get this working in my next blog post. Thanks for watching and I look forward to posting my next progress video update.



After capturing the footage of the blood splatter effect in the image above, I have decided that this specific blood splatter effect will primarily be used for head shots. Why? Because gamers love head shots!


Muzzle Flash Class Source Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Media;

namespace CycloneEngine
{
    public class MuzzleFlash
    {
        Texture2D[] flash;
        SpriteBatch spriteBatch;
        public bool show;
        int frame;
        int startFrame = 1;

        public MuzzleFlash(SpriteBatch sB, Texture2D[] f)
        {
            flash = f;
            spriteBatch = sB;
            show = false;
            frame = startFrame;
        }

        public void activate()
        {
            show = true;
            frame++;
            if (frame == flash.Length - 1)
            {
                frame = startFrame;
                show = true;
            }
        }

        public void update()
        {
            if (show)
            {
                show = true;
                frame++;
                if (frame == flash.Length - 1)
                {
                    frame = startFrame;
                    show = false;
                }
            }
        }

        public void draw()
        {
            if (show)
            {
                Vector2 middle = new Vector2(Constants.SCRWIDTH / 2 - 500, Constants.SCRHEIGHT / 2 - 300);
                spriteBatch.Draw(flash[frame], middle, Color.White);
            }
        }
    }
}


Game Class Source for Muzzle Flash:
       In the Game Class, we need a variable to hold our muzzle flash class information so we declare this at the top. We will name it muzzleflash:

public static MuzzleFlash muzzleflash;


Then we need to load the muzzle flash texture files inside the Load Content Method: 

Texture2D[] flash = new Texture2D[24];
            for (int i = 0; i < 24; i++)
            {
                if (i < 10)
                    flash[i] = content.Load<Texture2D>("Images/muzzleflash/Muzzle_0000" + i.ToString());
                else
                    flash[i] = content.Load<Texture2D>("Images/muzzleflash/Muzzle_000" + i.ToString());
            }
            muzzleflash = new MuzzleFlash(spriteBatch, flash);


We need to update the muzzle flash so place the following in the Update Method: 

muzzleflash.Update();


In my Handle Player Input Method or however you want to activate the muzzle flash, add this: 

if (gamePadState.Triggers.Right > 0)
 {
   muzzleflash.activate();
 }


Then in the Draw Method to display it on-screen, add this: 

            spriteBatch.Begin();
            muzzleflash.draw();
            spriteBatch.End();


       The blood splatter class for now is the same source code for the muzzle flash. The only real difference is that it is positioned in 3D space when drawn.


Blood Splatter Class Source Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace CycloneEngine
{
    public class Blood
    {
        Texture2D[] blood;
        SpriteBatch spriteBatch;
        public bool show;
        int frame;
        int startFrame = 1;

        public Blood(SpriteBatch sB, Texture2D[] f)
        {
            blood = f;
            spriteBatch = sB;
            show = false;
            frame = startFrame;
     
        }

        public void activate()
        {
            show = true;
            frame++;
            if (frame == blood.Length)
            {
                frame = startFrame;
                show = true;
            }
        }

        public void update()
        {
            if (show)
            {
                show = true;
                frame++;
                if (frame == blood.Length)
                {
                    frame = startFrame;
                    show = false;
                }
            }
        }

        public void draw()
        {
            if (show)
            {
                Vector2 middle = new Vector2(Constants.SCRWIDTH / 2 - 500, Constants.SCRHEIGHT / 2 - 300);
                spriteBatch.Draw(blood[frame], middle, Color.White);

            }
        }
    }
}


Game Class Source for Blood Splatter: 
     In the Game Class, we need a variable to hold our blood class information so we declare this at the top. We will simply name it blood. We also need to create a Basic Effect. 

public static Blood blood;
BasicEffect basicEffect;


In the Load Content Method, add the following:

  basicEffect = new BasicEffect(ScreenManager.GraphicsDevice)
            {
                   TextureEnabled = true
                   VertexColorEnabled = true,
            };

 Texture2D[] texture = new Texture2D[64];
            for (int i = 0; i < 64; i++)
            {
                if (i < 10)
                    texture[i] = content.Load<Texture2D>("Images/bloodsplat/Blood_0000" + i.ToString());
                else
                    texture[i] = content.Load<Texture2D>("Images/bloodsplat/Blood_000" + i.ToString());
            }

  blood = new Blood(spriteBatch, texture);


We need to update the blood splatter, so place the following in the Update Method: 

blood.Update();


Then we activate the blood splatter the same way we activated the muzzle flash:

blood.Activate();


In the Draw Method, add the following: 

            Matrix view = Matrix.CreateLookAt(camera.Position,
                                              camera.Position + camera.ChaseDirection,
                                              Vector3.Up);

            Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                                                                    aspectRatio,
                                                                    0.1f, 500);

            basicEffect.View = view;
            basicEffect.Projection = projection;


            spriteBatch.Begin(0, null, null, DepthStencilState.DepthRead, RasterizerState.CullNone, basicEffect);
            blood.draw();
            spriteBatch.End();


       I will create a new billboard class for the blood splatter so that it always turns and faces the camera to be read better and appear more fully 3D. If you have found this blog post helpful, please comment below. Thanks for reading. 


No comments:

Post a Comment