topical media & game development

talk show tell print

game-xna-intro-XnaShooter-Game-EffectManager.cs / cs



  // Project: XnaShooter, File: EffectManager.cs
  // Namespace: XnaShooter.Game, Class: EffectManager
  // Path: C:\code\XnaShooter\Game, Author: Abi
  // Code lines: 18, Size of file: 349 Bytes
  // Creation date: 27.12.2006 06:53
  // Last modified: 27.12.2006 12:51
  // Generated with Commenter by abi.exDream.com
  
  #region Using directives
  using System;
  using System.Collections.Generic;
  using System.Text;
  using XnaShooter.Game;
  using XnaShooter.Helpers;
  using XnaShooter.Graphics;
  using XnaShooter.Sounds;
  using Texture = XnaShooter.Graphics.Texture;
  using Microsoft.Xna.Framework;
  using Microsoft.Xna.Framework.Graphics;
  using Microsoft.Xna.Framework.Input;
  #endregion
  
  namespace XnaShooter.Game
  {
  
<summary> Effect manager. Used in 2 ways: As instance class by XnaShooterGame to load and show all used effect textures. And as a static class to add and manage all new effects (which makes it much easier for external use). </summary> public class EffectManager : IGraphicContent { #region Variables private static string[] EffectTextureFilenames = new string[] { "MgHit", "Plasma", "Smoke", "ExplosionRing", "LightEffect", "FireBall", "FireStar", "SimpleFlare", }; private Texture[] effectTextures = null;

  
<summary> Effect texture types </summary> enum EffectTextureType { MgHit, Plasma, Smoke, ExplosionRing, LightEffect, FireBall, FireStar, SimpleFlare, } // enum EffectTextureTypes

                  private static string[] ExplosionTextureFilenames = new string[]
                          {
                                  "Destroy",
                                  "BigExplosion",
                          };
                  private AnimatedTexture[] explosionTextures = null;
  
<summary> Explosion texture type </summary> enum ExplosionTextureType { SmallExplosion, BigExplosion, } // enum ExplosionTextureType

                  public enum EffectSoundType
                  {
                          Health,
                          NewWeapon,
                          MgShoot,
                          MgHit,
                          PlasmaShoot,
                          RocketShoot,
                          RocketHit,
                          GattlingShoot,
                          EnemyShoot,
                          ShipHit,
                          Explosion,
                          BigExplosion,
                          MgShootEnemy,
                  } // enum ExplosionTextureType
                  #endregion
  
                  #region Constructor
  
<summary> Create effect manager </summary> public EffectManager() { Load(); BaseGame.RegisterGraphicContentObject(this); } // EffectManager() #endregion

                  #region Load
                  public void Load()
                  {
                          // Load textures
                          if (effectTextures == null)
                          {
                                  effectTextures = new Texture[EffectTextureFilenames.Length];
                                  for (int num = 0; num < effectTextures.Length; num++)
                                  {
                                          effectTextures[num] = new Texture(EffectTextureFilenames[num]);
                                  } // for (num)
                          } // if
  
                          if (explosionTextures == null)
                          {
                                  explosionTextures =
                                          new AnimatedTexture[ExplosionTextureFilenames.Length];
                                  for (int num = 0; num < explosionTextures.Length; num++)
                                  {
                                          explosionTextures[num] = new AnimatedTexture(
                                                  ExplosionTextureFilenames[num]);
                                  } // for (num)
                          } // if
                  } // Load()
                  #endregion
  
                  #region Dispose
                  public void Dispose()
                  {
                          effectTextures = null;
                          explosionTextures = null;
                  } // Dispose()
                  #endregion
  
                  #region Effect types
  
<summary> Effect types, only used internally. Use the Add methods to add specific effects, which often contain multiple internal effects. </summary> public enum EffectType { <summary> Machine Gun Shoot effect. Used for Raptor and Hunter guns. </summary> MgShoot, <summary> Machine Gun Hit effect. Also used for MiniGun and added to big explosions, rotate and use alpha, very small, also don't play all the time. </summary> MgHit, <summary> Plasma effects are used for Mammuts (primary weapon), they are very similar to the Quake3 Plasma Gun. </summary> Plasma, <summary> Same effect as MgShoot, just longer </summary> PlasmaShoot, <summary> Fireball effect ala mg shoot. </summary> RocketShoot, <summary> Fire ball effect for bombers in game. Slow flying particles. </summary> FireBall, <summary> Smoke effect for rockts and ships </summary> Smoke, <summary> Flare effect for rockets and ships to indicate burning eginiton. Basically just a red/yellow spot (heat). </summary> Flare, <summary> Big explosion when units are dying. </summary> BigExplosion, <summary> Smaller explosion for smaller units or smaller explosion effects. </summary> SmallExplosion, <summary> Flame explosions happen when the rocket hits. </summary> FlameExplosion, <summary> Fire star effect for big explosion. </summary> FireStar, <summary> Ring effect for bigger explosions to indicate heavy explosions. </summary> ExplosionRing, <summary> Light effect (same texture as the one from the Lens flare). This effect makes the screen more bright, so do this effect after the other effects (kinda post screen). Looks very good in combination with glow, burn and explosions. We get 3 kinds: LightShort for a short burst of light (500 ms), LightLong (1.5 seconds) for big explosions and stuff, LightInstant for immediate effects, no fade in/out. </summary> LightVeryShort, LightShort, LightLong, LightInstant, <summary> Simple glow effect (same as glow behind items). Used to indicate enemies+weapons (red) and friends (green). </summary> FriendlyGlow, <summary> 2 enums to save storing color values in effect class. </summary> EnemyGlow, <summary> No effect, just for assigning no effect to a variable. </summary> None, } // enum EffectType

  
<summary> Helper list for all effects. Holds the max. time the effect is active. It will fade in from 0-10% and fade out from 50-100%. Explosion effects don't fade in, they just fade out at end (80-100%) </summary> static int[] EffectMaxTime = new int[] { 35, // MgShoot, 100, // MgHit, 0, // Plasma, 89, // PlasmaShoot 250, // RocketShoot 0, // FireBall, 1500,//2000,//4250, // Smoke, 0, // Flare, 1800,//2100, // BigExplosion, 1300,//1500, // SmallExplosion, 1400,//1650, // FlameExplosion, 500, // FireStar, 2000,//2500, // ExplosionRing, 200, // LightVeryShort, 575,//625,//750, // LightShort, 1300,//1500, // LightLong, 0, // LightInstant, 0, // FriendlyGlow, 0, // EnemyGlow, };

  
<summary> Effect texture nums, links to effectTextures except for the explosions, which use explosionTextures. </summary> static int[] EffectTextureNum = new int[] { (int)EffectTextureType.FireStar, (int)EffectTextureType.MgHit, (int)EffectTextureType.Plasma, (int)EffectTextureType.FireStar, (int)EffectTextureType.FireStar, (int)EffectTextureType.FireBall, (int)EffectTextureType.Smoke, (int)EffectTextureType.SimpleFlare, (int)ExplosionTextureType.BigExplosion, (int)ExplosionTextureType.SmallExplosion, (int)ExplosionTextureType.SmallExplosion, (int)EffectTextureType.FireStar, (int)EffectTextureType.ExplosionRing, (int)EffectTextureType.LightEffect, (int)EffectTextureType.LightEffect, (int)EffectTextureType.LightEffect, (int)EffectTextureType.LightEffect, (int)EffectTextureType.LightEffect, (int)EffectTextureType.LightEffect, }; #endregion

                  #region Line Handling
  
<summary> Line helper class. Remembers all the lines we added. </summary> class Line { public Vector3 startPos, endPos; public Color startColor, endColor; float time, maxTime; public int startPosId, endPosId;

  
<summary> Create line </summary> <param name="setStartPos">Set start position</param> <param name="setEndPos">Set end position</param> <param name="setColor">Set color</param> <param name="setMaxTime">Set maximum time</param> public Line(Vector3 setStartPos, Vector3 setEndPos, Color setStartColor, Color setEndColor, int setMaxTime, int setStartPosId, int setEndPosId) { startPos = setStartPos; endPos = setEndPos; startColor = setStartColor; endColor = setEndColor; time = 0; maxTime = setMaxTime; startPosId = setStartPosId; endPosId = setEndPosId; } // Line(setStartPos, setEndPos, setColor)

  
<summary> Render </summary> <returns>Returns true if time is over and line should be removed from the lines list.</returns> public bool Render() { time += BaseGame.ElapsedTimeThisFrameInMs;// ElapsedTime.MsLastFrame; if (time >= maxTime) return true;

                                  BaseGame.DrawLine(startPos, endPos,
                                          // Looks better than with alpha fading
                                          startColor, endColor);
                                  //Color.FromArgb(
                                  //(byte)(col.A * (1.0f - ((float)time / (float)maxTime))), col));
                                  return false;
                          } // Render()
                  } // class Line
                  static List<Line> lines = new List<Line>();
  
  
<summary> Add line from startPoint to endPoint with specific color. Used for MG effects (randomly every 10 shoots), alpha lines with dark yellow colors (see WeaponManager). Lines are always rendered instantly and fade out quickly. </summary> <param name="startPoint">Start point</param> <param name="endPoint">End point</param> <param name="col">Color</param> private static void AddLine(Vector3 startPoint, Vector3 endPoint, Color startColor, Color endColor, int startPosId, int endPosId) { lines.Add(new Line(startPoint, endPoint, startColor, endColor, 100, startPosId, endPosId)); } // AddLine(startPoint, endPoint, col) #endregion

                  #region Effect helper class
  
<summary> Effect </summary> class Effect { #region Variables <summary> Position of effect, moving is not supported, use instant effects for moving stuff (e.g. weapon projectiles). </summary> public Vector3 pos; <summary> Size and endSize, usually the same, but some effects like ExplosionRing will expand over time (from 1.0f to 50.0f very quickly) </summary> public float size, endSize; <summary> Effect type, see above. </summary> public EffectType type; <summary> Time and max time, if time reaches maxTime, the effect is over. </summary> public float time, maxTime; <summary> Rotation, set to a specific value for more different looks of same effects. Will stay rotated this way. Most effects just use 0. But plasma and fireball effects look much better rotated this way :) </summary> public float rotation; <summary> Color to colorizise effects, often used to darken down or make effect more transparent. Sometimes we color effects like glow or light to indicate player colors (or enemy/friendly status). </summary> public Color color; <summary> Id for this effect, used to update stuff. </summary> public int id;

  
<summary> Helpers for RenderBillboardOnGround, used for Ring effect. This allows us to rotate the ring effect in space. </summary> public Vector3 vecGroundRight, vecGroundUp; #endregion

                          #region Properties
  
<summary> Is light effect </summary> <returns>Bool</returns> public bool IsLightEffect { get { return type == EffectType.LightVeryShort || type == EffectType.LightShort || type == EffectType.LightLong || type == EffectType.LightInstant; } // get } // IsLightEffect

  
<summary> Is explosion </summary> <returns>Bool</returns> public bool IsExplosion { get { return type == EffectType.SmallExplosion || type == EffectType.BigExplosion || type == EffectType.FlameExplosion; } // get } // IsExplosion

  
<summary> Is ring </summary> <returns>Bool</returns> public bool IsRing { get { return type == EffectType.ExplosionRing; } // get } // IsRing #endregion

                          #region Constructor
  
<summary> Create effect </summary> <param name="setPos">Set position</param> <param name="setSize">Set size</param> <param name="setType">Set type</param> public Effect(Vector3 setPos, float setSize, EffectType setType, int setId) { position = pos = setPos; size = endSize = setSize; type = setType; time = 0; maxTime = EffectMaxTime[(int)type]; rotation = 0; color = Color.White; id = setId; } // Effect(setPos, setSize, setType) #endregion

                          #region Distance
  
<summary> Helper for calculating distance. </summary> public float distance; //*obs <summary> Also precalculate position here, will be changed for light effects to add little offset to fix z buffer errors. </summary> private Vector3 position; //

  
  
<summary> Calc distance, will be called before sorting (it is faster to calculate it only once and then compare multiple times). </summary> public void CalcDistance(Vector3 cameraPos) { //*obs // First get position and offset it for lights (always on top) position = pos; // Reduce position nearer to camera for light effects. if (IsLightEffect) { Vector3 distVector = pos - cameraPos; distVector.Normalize(); position -= distVector * 2.0f;// 2.5f; } // if (IsLightEffect) //

  
  
                                  distance = (position - cameraPos).Length();
                          } // CalcDistance(cameraPos)
                          #endregion
  
                          #region Render
  
<summary> Render </summary> <returns>True if effect is at end and has to be removed</returns> public bool Render(Vector3 camPos, EffectManager effectManager) { // Max. distance for visible effects. const float MaxDistance = BaseGame.FarPlane;// *0.66f;

                                  // Calculate current size
                                  float timePercent = maxTime == 0 ? 0 : (float)time / (float)maxTime;
                                  float currentSize = size + (endSize - size) * timePercent;
  
                                  // Calculate alpha, always 100% for instant effects.
                                  // Else it will fade in from 0-10% and fade out from 75-100%.
                                  // Explosion effects don't fade in, they just fade out at end (80-100%)
                                  Color currentColor = color;
  
                                  if (IsExplosion)
                                  {
                                          if (timePercent > 0.8f)
                                                  currentColor = ColorHelper.FromArgb((byte)
                                                          (color.A * (1.0f - (timePercent - 0.8f) * 5.0f)), color);
                                          AnimatedTexture aniTex =
                                                  effectManager.explosionTextures[EffectTextureNum[(int)type]];
                                          //obs: aniTex.Select((int)(timePercent * aniTex.AnimationLength));
                                          Billboard.Render(aniTex,
                                                  (int)(timePercent * aniTex.AnimationLength),
                                                  Billboard.BlendMode.NormalAlphaBlending,
                                                  position, currentSize, rotation, currentColor);
                                  } // if (IsExplosion)
                                  else
                                  {
                                          float alpha = 1.0f;
                                          if (IsLightEffect)
                                          {
                                                  // Don't change color, but change size
                                                  if (timePercent > 0.5f)
                                                          currentSize = currentSize *
                                                                  (1.0f - (timePercent - 0.5f) * 1.9f);
                                          } // if (IsLightEffect)
                                          else if (maxTime > 0 &&
                                                  timePercent < 0.1f)
                                                  alpha = timePercent * 10.0f;
                                          else if (type == EffectType.Smoke)
                                                  alpha = 1.0f - (timePercent - 0.1f) / 0.9f;
                                          else if (timePercent > 0.75f)
                                                  alpha = 1.0f - (timePercent - 0.75f) * 4.0f;
  
                                          // Fade out if really far away!
                                          if (distance > MaxDistance * 0.75f)
                                                  alpha *= 1.0f -
                                                          ((distance - MaxDistance * 0.75f) / (MaxDistance * 0.25f));
  
                                          if (alpha != 1.0f)
                                          {
                                                  if (alpha > 1.0f)
                                                          alpha = 1.0f;
                                                  if (alpha < 0.0f)
                                                          alpha = 0.0f;
  
                                                  currentColor = ColorHelper.FromArgb((byte)(color.A * alpha), color);
                                          } // if (alpha)
  
                                          //obs:
                                          //effectManager.effectTextures[EffectTextureNum[(int)type]].Select();
                                          if (IsRing)
                                                  Billboard.RenderOnGround(
                                                          effectManager.effectTextures[EffectTextureNum[(int)type]],
                                                          position, currentSize, rotation, currentColor,
                                                          vecGroundRight, vecGroundUp);
                                          else if (IsLightEffect)
                                                  Billboard.Render(
                                                          effectManager.effectTextures[EffectTextureNum[(int)type]].
                                                          XnaTexture, Billboard.BlendMode.LightEffect,
                                                          position, currentSize, currentColor);
                                          else
                                                  Billboard.Render(
                                                          effectManager.effectTextures[EffectTextureNum[(int)type]],
                                                          position, currentSize, rotation, currentColor);
                                  } // else
  
                                  // Increase time
                                  time += BaseGame.ElapsedTimeThisFrameInMs;//.MsLastFrame;
                                  // Quit if time is over, also quit if out of visible area!
                                  if (time >= maxTime ||
                                          distance > MaxDistance)
                                          return true;
  
                                  return false;
                          } // Render()
                          #endregion
                  } // class Effect
  
                  static List<Effect> effects = new List<Effect>();
  
                  public static int NumberOfEffects
                  {
                          get
                          {
                                  return effects.Count;
                          } // get
                  } // NumberOfEffects
  
  
<summary> Compare effects for effects.Sort in HandleAllEffects. </summary> <param name="effect1">Effect 1</param> <param name="effect2">Effect 2</param> <returns>Int</returns> private static int CompareEffects(Effect effect1, Effect effect2) { // Uncompareable because x or y is invalid, don't change stuff! if (effect1 == null || effect2 == null) return 0; else if (effect1.distance == effect2.distance) return 0; else if (effect1.distance < effect2.distance) return 1; else return -1; } // CompareEffects(effect1, effect2) #endregion

                  #region Add single effect
                  static int offsetCounter = 0;
  
<summary> Add effect at a specific position. Effects are either one-frame-only (e.g. plasma) or are animated and fade out after a while (explosions, smoke). Usually effects get bigger when they fade out (ring effect). Most effects are for big weapons like rockets or explosions when killing something. </summary> <param name="position">Position</param> <param name="type">Effect type</param> <param name="scaleFactor">Additional scale factor, usually 1.0f, but sometimes we want bigger smokes or explosions.</param> <param name="useRotationForPlasmaAndFireball">Use this rotation</param> <param name="setId">Set id</param> public static void AddEffect(Vector3 position, EffectType type, float scaleFactor, float useRotationForPlasmaAndFireball, int setId) { Effect effect = new Effect( position, scaleFactor, type, setId); // Add little offset for effects to prevent painting them on top of each // other and producing polygon clipping errors. offsetCounter = (offsetCounter + 1) % 18; effect.pos += new Vector3(0.004f, 0.006f, 0.008f) * offsetCounter;

                          // All additonal sizes, timeouts, etc. are hardcoded.
                          if (type == EffectType.Smoke)
                          {
                                  effect.endSize *= 2.0f;
                                  // Randomize smoke position a bit
                                  //already done:
                                  //effect.pos += RandomHelper.GetRandomVector3(-1.35f, +1.35f);
                                  // Use very low alpha for smoke effects (put many on top of each other)
                                  effect.color = ColorHelper.FromArgb(60, effect.color);
                          } // if (type)
                          else if (type == EffectType.Plasma ||
                                  type == EffectType.FireBall)
                          {
                                  effect.rotation = useRotationForPlasmaAndFireball;
                                  effect.color = ColorHelper.FromArgb(220, 190, 190, 190);
                          } // else if
                          else if (type == EffectType.FireStar ||
                                  type == EffectType.MgShoot ||
                                  type == EffectType.MgHit ||
                                  type == EffectType.PlasmaShoot)
                          {
                                  effect.rotation = RandomHelper.GetRandomFloat(
                                          0, (float)Math.PI * 2.0f);
                                  effect.endSize *= 1.7f;
                                  effect.color = ColorHelper.FromArgb(155, 255, 255, 255);
                          } // else if
                          else if (type == EffectType.ExplosionRing)
                          {
                                  effect.endSize *= 15.0f;
                                  // Randomize rotation for ring
                                  Matrix rotMatrix = Matrix.CreateRotationX(
                                          RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f)) *
                                          Matrix.CreateRotationY(
                                          RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f)) *
                                          Matrix.CreateRotationZ(
                                          RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f));
                                  effect.vecGroundRight = Vector3.TransformNormal(
                                          Billboard.vecGroundRight, rotMatrix);
                                  effect.vecGroundUp = Vector3.TransformNormal(
                                          Billboard.vecGroundUp, rotMatrix);
                          } // else if
                          else if (effect.IsExplosion)
                                  effect.endSize *= 1.3f;
                          else if (effect.IsLightEffect)
                          {
                                  effect.endSize *= 1.6f;
                                  effect.color = Color.White;// Color.FromArgb(255, 255, 255, 255);
                          } // else if
                          else if (type == EffectType.FriendlyGlow ||
                                  type == EffectType.EnemyGlow)
                          {
                                  // Put glow always behind objects, not in front
                                  Vector3 distVector = effect.pos - BaseGame.CameraPos;
                                  distVector.Normalize();
                                  effect.pos += distVector * 10.0f;
  
                                  if (type == EffectType.FriendlyGlow)
                                          effect.color = ColorHelper.FromArgb(120, 100, 255, 100);
                                  else
                                          effect.color = ColorHelper.FromArgb(160, 255, 40, 40);
                          } // else if
  
                          // And finally add to effects list
                          effects.Add(effect);
                  } // AddEffect(position, type)
                  
  
<summary> Add effect at a specific position. Effects are either one-frame-only (e.g. plasma) or are animated and fade out after a while (explosions, smoke). Usually effects get bigger when they fade out (ring effect). Most effects are for big weapons like rockets or explosions when killing something. </summary> <param name="position">Position</param> <param name="type">Effect type</param> <param name="scaleFactor">Additional scale factor, usually 1.0f, but sometimes we want bigger smokes or explosions.</param> <param name="useRotationForPlasmaAndFireball">Use this rotation</param> <param name="setId">Set id</param> public static void AddEffect(Vector3 position, EffectType type, float scaleFactor, float useRotationForPlasmaAndFireball) { AddEffect(position, type, scaleFactor, useRotationForPlasmaAndFireball, -1); } // AddEffect(position, type, scaleFactor) #endregion

                  #region Play sound effects
  
<summary> Play sound effect, adds 3d sound effect depending on the position. </summary> <param name="soundType">Sound type</param> public static void PlaySoundEffect(EffectSoundType soundType) { Sound.Play(soundType.ToString()); } // PlaySoundEffect(soundType, volume) #endregion

                  #region Add effect helper methods
                  #region AddMgEffect
                  static readonly Color MgLineStartColor = ColorHelper.FromArgb(255, 206, 180, 73);
                  static readonly Color MgLineEndColor = ColorHelper.FromArgb(255, 126, 110, 53);
  
  
<summary> Add mg effect. First we will render a line from startPos to endPos in MgLineColor. Then we also display a startPos effect (small fire star and light) and an endPos effect (mg hit effect and light). </summary> <param name="startPos">Start position</param> <param name="endPos">End position</param> <param name="startPosId">Start position id</param> <param name="endPosId">End position id</param> <param name="showTargetEffects">Show target effects only if we hit something, don't show if shoot goes out of the screen.</param> public static void AddMgEffect(Vector3 startPos, Vector3 endPos, int startPosId, int endPosId, bool showTargetEffects, bool playSound) { AddLine(startPos, endPos, MgLineStartColor, MgLineEndColor, startPosId, endPosId);

                          // Play sound effect, but not always and not so loud (we play many)
                          if (RandomHelper.GetRandomInt(4) == 0 &&
                                  BaseGame.EveryMs(50) ||
                                  playSound)
                                  PlaySoundEffect(EffectSoundType.MgShoot);
  
                          //if (BaseGame.EveryMs(150))
                          //{
                                  AddEffect(startPos, EffectType.MgShoot, 2.25f, 0.0f, startPosId);
                                  AddEffect(startPos, EffectType.LightShort, 3.0f, 0.0f, startPosId);
                          //} // if (BaseGame.EveryMs)
  
                          if (showTargetEffects)
                          {
                                  if (RandomHelper.GetRandomInt(5) < 3)
                                          PlaySoundEffect(EffectSoundType.MgHit);
  
                                  AddEffect(endPos, EffectType.MgHit, 4.0f, 0.0f, endPosId);
                                  AddEffect(endPos, EffectType.LightVeryShort, 6.0f, 0.0f, endPosId);
                          } // if (showTargetEffects)
                  } // AddMgEffect(startPos, endPos)
  
  
<summary> Add gattling effect. First we will render a line from startPos to endPos in MgLineColor. Then we also display a startPos effect (small fire star and light) and an endPos effect (mg hit effect and light). </summary> <param name="startPos">Start position</param> <param name="endPos">End position</param> <param name="startPosId">Start position id</param> <param name="endPosId">End position id</param> <param name="showTargetEffects">Show target effects only if we hit something, don't show if shoot goes out of the screen.</param> public static void AddGattlingEffect(Vector3 startPos, Vector3 endPos, int startPosId, int endPosId, bool showTargetEffects, bool playSound) { AddLine(startPos, endPos, MgLineStartColor, MgLineEndColor, startPosId, endPosId);

                          // Play sound effect, but not always and not so loud (we play many)
                          if (RandomHelper.GetRandomInt(4) == 0 &&
                                  BaseGame.EveryMs(150) ||
                                  playSound)
                                  PlaySoundEffect(EffectSoundType.GattlingShoot);
  
                          if (RandomHelper.GetRandomInt(3) == 0)//BaseGame.EveryMs(150))
                          {
                                  AddEffect(startPos, EffectType.MgShoot, 2.5f, 0.0f, startPosId);
                                  AddEffect(startPos, EffectType.LightShort, 3.5f, 0.0f, startPosId);
                          } // if (BaseGame.EveryMs)
  
                          if (showTargetEffects)
                          {
                                  if (RandomHelper.GetRandomInt(5) < 3)
                                          PlaySoundEffect(EffectSoundType.MgHit);
  
                                  AddEffect(endPos, EffectType.MgHit, 7.0f, 0.0f, endPosId);
                                  AddEffect(endPos, EffectType.LightVeryShort, 8.0f, 0.0f, endPosId);
                          } // if (showTargetEffects)
                  } // AddGattlingEffect(startPos, endPos)
  
  
<summary> Update mg effect </summary> <param name="updatedPos">Updated position</param> <param name="id">Id</param> public static void UpdateMgEffect(Vector3 updatedPos, int id) { //foreach (Line line in lines) for (int num=0; num<lines.Count; num++) { Line line = lines[num]; if (line.startPosId == id) line.startPos = updatedPos; if (line.endPosId == id) line.endPos = updatedPos; } // foreach (line)

                          //foreach (Effect effect in effects)
                          for (int num = 0; num < effects.Count; num++)
                          {
                                  Effect effect = effects[num];
                                  if (effect.id == id)
                                          effect.pos = updatedPos;
                          } // for
                  } // UpdateMgEffect(updatedPos, id)
  
                  /*
  
<summary> Update effect </summary> <param name="updatedPos">Updated position</param> <param name="id">Id</param> public static void UpdateEffect(Vector3 updatedPos, int id) { foreach (Effect effect in effects) if (effect.id == id) effect.pos = updatedPos; } // UpdateEffect(updatePos, id)

  
                  #endregion
  
                  #region AddFireFlash
                  public static void AddFireFlash(Vector3 pos)
                  {
                          AddEffect(pos, EffectType.MgShoot, 2.5f, 0.0f, -1);
                          AddEffect(pos, EffectType.LightLong, 5.0f, 0.0f, -1);
                  } // AddFireFlash(pos)
                  #endregion
  
                  #region AddPlasmaEffect
  
<summary> Add plasma effect. Shows plasma ball and light effect (both instant only). </summary> <param name="position">Position</param> <param name="size">Size</param> public static void AddPlasmaEffect(Vector3 pos, float rotation, float size) { AddEffect(pos, EffectType.Plasma, size, rotation); AddEffect(pos, EffectType.LightInstant, size * 2.5f, 0.0f); } // AddPlasmaEffect(position) #endregion

                  #region AddFireBallEffect
  
<summary> Add fire ball effect. Shows fire ball and light effect (both instant only). Also adds small smoke behind fireball (every 1/10 seconds). </summary> <param name="pos">Position</param> <param name="size">Size</param> public static void AddFireBallEffect(Vector3 pos, float rotation, float size) { AddEffect(pos, EffectType.FireBall, size, rotation); AddEffect(pos, EffectType.LightInstant, size * 2.5f, 0.0f);

                          if (BaseGame.EveryMs(75))
                          {
                                  AddEffect(
                                          pos + RandomHelper.GetRandomVector3(-size * 0.275f, +size * 0.275f),
                                          EffectType.Smoke, size,
                                          RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f));
                          } // if (BaseGame.EveryMs)
                  } // AddFireBallEffect(pos, rotation, size)
                  #endregion
  
                  #region AddRocketOrShipFlareAndSmoke
  
<summary> Add rocket or ship flare and smoke. First we show an instant flare effect at pos, then we add a smoke effect every 1/10 seconds. </summary> <param name="pos">Position</param> <param name="size">Size</param> <param name="speed">Speed of unit per second, very important for determinting how much smoke we should generate. </param> public static void AddRocketOrShipFlareAndSmoke( Vector3 pos, float size, float speed) { AddEffect(pos, EffectType.Flare, size, 0); AddEffect(pos, EffectType.LightInstant, size, 0); // Raptor speed: 220 -> smoke: 60ms // Lizard rocket speed: 250 -> smoke: 50ms // Mammut speed: 150 -> smoke: 100ms // Carrier speed: 20 -> smoke: >500ms // Formular: (1/speed)*1000*15 ms int msToCheck = (int)(speed > 0 ? (1 / speed) * 1000 * 15 : 1000.0f); // Don't go above 500, looks bad if (msToCheck > 500) msToCheck = 500; //*tst disabling if (BaseGame.EveryMs(msToCheck))//75)) { AddEffect( pos + RandomHelper.GetRandomVector3(-size * 0.275f, +size * 0.275f), EffectType.Smoke, size,// 1.5f, RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f)); } // if (BaseGame.EveryMs) //

  
                  } // AddRocketOrShipFlareAndSmoke(pos, size)
                  #endregion
  
                  #region AddExplosion
  
<summary> Add explosion, will use small or big explosion and several other effects depending on the size (small explosions only use SmallExplosion and a little light effect, big explosions use BigExplosion, ExplosionRing, Light effects, MgHit, FireStar and Smoke). </summary> <param name="pos">Position</param> <param name="size">Size</param> public static void AddExplosion(Vector3 pos, float size) { if (size <= 8 && RandomHelper.GetRandomInt(2) == 0) { AddEffect(pos, EffectType.SmallExplosion, size, RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f)); AddEffect(pos, EffectType.LightLong, size * 1.75f, 0); PlaySoundEffect(EffectSoundType.Explosion); } // if (size) else { // Skip this big explosion if already 4 or more are active, // too many big explosions look weird and cause problems // for too much overlapping graphic and sound effects. int numOfBigExplosions = 0; foreach (Effect effect in effects) if (effect.type == EffectType.BigExplosion) numOfBigExplosions++; if (numOfBigExplosions >= 4) return;

                                  AddEffect(pos, EffectType.BigExplosion, size,
                                          RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f));
                                  /*looks strange
                                  for (int i = 0; i < 1+(int)(size-10)/15; i++)
                                          AddEffect(pos, EffectType.ExplosionRing, size / 3.3f, 0);
  				 */
                                  if (size > 6)
                                          AddEffect(pos, EffectType.ExplosionRing, size / 6.0f, 0);
                                  else
                                          AddEffect(pos, EffectType.ExplosionRing, size / 8.0f, 0);
  
                                  AddEffect(pos, EffectType.LightLong, size * 2.5f, 0);
                                  PlaySoundEffect(size > 9 ?
                                          EffectSoundType.BigExplosion :
                                          EffectSoundType.Explosion);
                          } // else
  
                          for (int i = 0; i < (int)size/2; i++)
                          {
                                  Vector3 offset = RandomHelper.GetRandomVector3(-size, +size);
                                  AddEffect(pos + offset, EffectType.Smoke, size / 2.66f, 0);
                          } // for (int)
                  } // AddExplosion(pos, size)
  
  
<summary> Add hit explosion </summary> <param name="pos">Position</param> <param name="size">Size</param> public static void AddHitExplosion(Vector3 pos, float size) { AddEffect(pos, EffectType.SmallExplosion, size, RandomHelper.GetRandomFloat(0, (float)Math.PI * 2.0f)); AddEffect(pos, EffectType.LightLong, size * 1.75f, 0); PlaySoundEffect(EffectSoundType.Explosion);

                          for (int i = 0; i < (int)size / 4; i++)
                          {
                                  Vector3 offset = RandomHelper.GetRandomVector3(-size, +size);
                                  AddEffect(pos + offset, EffectType.Smoke, size / 1.66f, 0);
                          } // for (int)
                  } // AddHitExplosion(pos, size)
                  #endregion
  
                  #region AddFlameExplosion
  
<summary> Add flame explosion for the lizard shoot, high splash value. </summary> <param name="pos">Position</param> public static void AddFlameExplosion(Vector3 pos, bool playSound) { AddEffect(pos, EffectType.FlameExplosion, 2.5f, 0); AddEffect(pos, EffectType.LightLong, 5.5f, 0); if (playSound) PlaySoundEffect(EffectSoundType.RocketHit);

                          float size = 8;// 120;//40;
                          for (int i = 0; i < 2; i++)
                          {
                                  Vector3 offset = RandomHelper.GetRandomVector3(-size/2, +size/2);
                                  AddEffect(pos + offset, EffectType.FlameExplosion, size / 4.5f, 0);
                          } // for (int)
  
                          for (int i = 0; i < 2; i++)
                          {
                                  Vector3 offset = RandomHelper.GetRandomVector3(-size, +size);
                                  AddEffect(pos + offset, EffectType.Smoke, size / 2.85f, 0);//1.66f, 0);
                          } // for (int)
                  } // AddFlameExplosion(pos)
                  
  
<summary> Add flame explosion for the lizard shoot, high splash value. </summary> <param name="pos">Position</param> public static void AddFlameExplosion(Vector3 pos) { AddFlameExplosion(pos, true); } // AddFlameExplosion(pos) #endregion #endregion

                  #region Handle all effects
  
<summary> Handle all effects </summary> public void HandleAllEffects() { // First draw lines List<Line> linesToRemove = new List<Line>(); foreach (Line line in lines) if (line.Render()) linesToRemove.Add(line);

                          // Now remove all lines we don't need anymore
                          foreach (Line lineToBeRemoved in linesToRemove)
                                  lines.Remove(lineToBeRemoved);
  
                          // Render all lines. Not done automatically by manager because of
                          // z buffer issues and we want to paint over the lines.
                          BaseGame.FlushLineManager3D();
  
                          Vector3 camPos = BaseGame.CameraPos;
                          /*
                          // Sort effects by distance! First calculate all distances
                          foreach (Effect effect in effects)
                                  effect.CalcDistance(camPos);
  
                          // Sort whole effects list based on the distances
                          effects.Sort(CompareEffects);
  			 */
  
                          // Use temp list for removing, then remove after the foreach loop.
                          List<Effect> remEffectsToRemove = new List<Effect>();
                          //foreach (Effect effect in effects)
                          for (int num=0; num<effects.Count; num++)
                          {
                                  Effect effect = effects[num];
                                  if (effect.Render(camPos, this))
                                          remEffectsToRemove.Add(effect);
                          } // foreach (effect)
  
                          // Finish
                          Billboard.RenderBillboards();
  
                          // Remove elements that returned true in Render.
                          //foreach (Effect effectToRemove in remEffectsToRemove)
                          for (int num=0; num<remEffectsToRemove.Count; num++)
                                  effects.Remove(remEffectsToRemove[num]);
                  } // HandleAllEffects()
                  #endregion
  
                  #region Unit Testing
  if DEBUG
  
<summary> Effect tests </summary> public static void TestEffects() { TestGame.Start( "TestEffects", delegate { }, delegate { //GraphicForm.LineManager3D.AddLine( // new Vector3(0, 0, 0), new Vector3(100, 100, 100), // Color.White);

                                          // Press 1-0 for creating effects (in center of scene)
                                          if (Input.Keyboard.IsKeyDown(Keys.D1) &&
                                                  BaseGame.EveryMs(200))
                                                  AddMgEffect(
                                                          new Vector3(-10.0f, 0, -10),
                                                          new Vector3((BaseGame.TotalTimeMs % 3592) / 100.0f, 25, +100),
                                                          0, 1, true, true);//0, 1, true, true, true);
  
                                          if (Input.Keyboard.IsKeyDown(Keys.D2))
                                          {
                                                  AddPlasmaEffect(new Vector3(-50.0f, 0.0f, 0.0f), 0.5f, 5);
                                                  AddPlasmaEffect(new Vector3(0.0f, 0.0f, 0.0f), 1.5f, 5);
                                                  AddPlasmaEffect(new Vector3(50.0f, 0.0f, 0.0f), 0.0f, 5);
                                          } // if (Input.Keyboard.IsKeyDown(Keys.D2])
  
                                          if (Input.Keyboard.IsKeyDown(Keys.D3))
                                          {
                                                  AddFireBallEffect(new Vector3(-50.0f, +10.0f, 0.0f), 0.0f, 10);
                                                  AddFireBallEffect(new Vector3(0.0f, +10.0f, 0.0f),
                                                          (float)Math.PI / 8, 10);
                                                  AddFireBallEffect(new Vector3(50.0f, +10.0f, 0.0f),
                                                          (float)Math.PI * 3 / 8, 10);
                                          } // if (Input.Keyboard.IsKeyDown(Keys.D3])
  
                                          if (Input.Keyboard.IsKeyDown(Keys.D4))
                                                  AddRocketOrShipFlareAndSmoke(
                                                          new Vector3((BaseGame.TotalTimeMs % 4000) / 40.0f, 0, 0),
                                                          5.0f, 150.0f);
  
                                          if (Input.Keyboard.IsKeyDown(Keys.D5) &&
                                                  BaseGame.EveryMs(1000))
                                                  AddExplosion(Vector3.Zero, 9.0f);
                                          if (Input.Keyboard.IsKeyDown(Keys.D6) &&
                                                  BaseGame.EveryMs(1500))
                                                  AddExplosion(Vector3.Zero, 18.0f);
                                          if (Input.Keyboard.IsKeyDown(Keys.D7) &&
                                                  BaseGame.EveryMs(2000))
                                                  AddExplosion(Vector3.Zero, 32.0f);
                                          if (Input.Keyboard.IsKeyDown(Keys.D8) &&
                                            BaseGame.EveryMs(1500))
                                                  AddFlameExplosion(Vector3.Zero);
                                          
                                          // Play a couple of sound effects
                                          if (Input.Keyboard.IsKeyDown(Keys.P) &&
                                                  BaseGame.EveryMs(500))
                                                  PlaySoundEffect(EffectSoundType.PlasmaShoot);
                                          if (Input.Keyboard.IsKeyDown(Keys.F) &&
                                                  BaseGame.EveryMs(500))
                                                  PlaySoundEffect(EffectSoundType.EnemyShoot);
                                          if (Input.Keyboard.IsKeyDown(Keys.B) &&
                                                  BaseGame.EveryMs(250))
                                                  PlaySoundEffect(EffectSoundType.NewWeapon);
                                          if (Input.Keyboard.IsKeyDown(Keys.L) &&
                                                  BaseGame.EveryMs(1500))
                                                  PlaySoundEffect(EffectSoundType.RocketShoot);
                                          if (Input.Keyboard.IsKeyDown(Keys.H) &&
                                                  BaseGame.EveryMs(500))
                                                  PlaySoundEffect(EffectSoundType.RocketHit);
                                          if (Input.Keyboard.IsKeyDown(Keys.T) &&
                                                  BaseGame.EveryMs(500))
                                                  PlaySoundEffect(EffectSoundType.Health);
  
                                          // We have to render the effects ourselfs because
                                          // it is usually done in XnaShooterGame!
                                          // Finally render all effects (before applying post screen effects)
                                          BaseGame.effectManager.HandleAllEffects();
  
                                          TextureFont.WriteText(0, 30, 
                                                  "totalTimeMs="+BaseGame.TotalTimeMs);
                                  });
                  } // TestEffects()
  endif
                  #endregion
          } // class EffectManager
  } // namespace XnaShooter.Game
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.