// 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
{
///
/// 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).
///
public class EffectManager : IGraphicContent
{
#region Variables
private static string[] EffectTextureFilenames = new string[]
{
"MgHit",
"Plasma",
"Smoke",
"ExplosionRing",
"LightEffect",
"FireBall",
"FireStar",
"SimpleFlare",
};
private Texture[] effectTextures = null;
///
/// Effect texture types
///
enum EffectTextureType
{
MgHit,
Plasma,
Smoke,
ExplosionRing,
LightEffect,
FireBall,
FireStar,
SimpleFlare,
} // enum EffectTextureTypes
private static string[] ExplosionTextureFilenames = new string[]
{
"Destroy",
"BigExplosion",
};
private AnimatedTexture[] explosionTextures = null;
///
/// Explosion texture type
///
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
///
/// Create effect manager
///
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
///
/// Effect types, only used internally. Use the Add methods to
/// add specific effects, which often contain multiple internal effects.
///
public enum EffectType
{
///
/// Machine Gun Shoot effect. Used for Raptor and Hunter guns.
///
MgShoot,
///
/// 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.
///
MgHit,
///
/// Plasma effects are used for Mammuts (primary weapon),
/// they are very similar to the Quake3 Plasma Gun.
///
Plasma,
///
/// Same effect as MgShoot, just longer
///
PlasmaShoot,
///
/// Fireball effect ala mg shoot.
///
RocketShoot,
///
/// Fire ball effect for bombers in game. Slow flying particles.
///
FireBall,
///
/// Smoke effect for rockts and ships
///
Smoke,
///
/// Flare effect for rockets and ships to indicate burning eginiton.
/// Basically just a red/yellow spot (heat).
///
Flare,
///
/// Big explosion when units are dying.
///
BigExplosion,
///
/// Smaller explosion for smaller units or smaller explosion effects.
///
SmallExplosion,
///
/// Flame explosions happen when the rocket hits.
///
FlameExplosion,
///
/// Fire star effect for big explosion.
///
FireStar,
///
/// Ring effect for bigger explosions to indicate heavy explosions.
///
ExplosionRing,
///
/// 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.
///
LightVeryShort,
LightShort,
LightLong,
LightInstant,
///
/// Simple glow effect (same as glow behind items).
/// Used to indicate enemies+weapons (red) and friends (green).
///
FriendlyGlow,
///
/// 2 enums to save storing color values in effect class.
///
EnemyGlow,
///
/// No effect, just for assigning no effect to a variable.
///
None,
} // enum EffectType
///
/// 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%)
///
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,
};
///
/// Effect texture nums, links to effectTextures except for the
/// explosions, which use explosionTextures.
///
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
///
/// Line helper class. Remembers all the lines we added.
///
class Line
{
public Vector3 startPos, endPos;
public Color startColor, endColor;
float time, maxTime;
public int startPosId, endPosId;
///
/// Create line
///
/// Set start position
/// Set end position
/// Set color
/// Set maximum time
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)
///
/// Render
///
/// Returns true if time is over and line should be removed
/// from the lines list.
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 lines = new List();
///
/// 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.
///
/// Start point
/// End point
/// Color
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
///
/// Effect
///
class Effect
{
#region Variables
///
/// Position of effect, moving is not supported, use instant effects
/// for moving stuff (e.g. weapon projectiles).
///
public Vector3 pos;
///
/// Size and endSize, usually the same, but some effects like
/// ExplosionRing will expand over time (from 1.0f to 50.0f very quickly)
///
public float size, endSize;
///
/// Effect type, see above.
///
public EffectType type;
///
/// Time and max time, if time reaches maxTime, the effect is over.
///
public float time, maxTime;
///
/// 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 :)
///
public float rotation;
///
/// 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).
///
public Color color;
///
/// Id for this effect, used to update stuff.
///
public int id;
///
/// Helpers for RenderBillboardOnGround, used for Ring effect.
/// This allows us to rotate the ring effect in space.
///
public Vector3 vecGroundRight, vecGroundUp;
#endregion
#region Properties
///
/// Is light effect
///
/// Bool
public bool IsLightEffect
{
get
{
return type == EffectType.LightVeryShort ||
type == EffectType.LightShort ||
type == EffectType.LightLong ||
type == EffectType.LightInstant;
} // get
} // IsLightEffect
///
/// Is explosion
///
/// Bool
public bool IsExplosion
{
get
{
return type == EffectType.SmallExplosion ||
type == EffectType.BigExplosion ||
type == EffectType.FlameExplosion;
} // get
} // IsExplosion
///
/// Is ring
///
/// Bool
public bool IsRing
{
get
{
return type == EffectType.ExplosionRing;
} // get
} // IsRing
#endregion
#region Constructor
///
/// Create effect
///
/// Set position
/// Set size
/// Set type
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
///
/// Helper for calculating distance.
///
public float distance;
//*obs
///
/// Also precalculate position here, will be changed for light effects
/// to add little offset to fix z buffer errors.
///
private Vector3 position;
//*/
///
/// Calc distance, will be called before sorting (it is faster to
/// calculate it only once and then compare multiple times).
///
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
///
/// Render
///
/// True if effect is at end and has to be removed
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 effects = new List();
public static int NumberOfEffects
{
get
{
return effects.Count;
} // get
} // NumberOfEffects
///
/// Compare effects for effects.Sort in HandleAllEffects.
///
/// Effect 1
/// Effect 2
/// Int
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;
///
/// 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.
///
/// Position
/// Effect type
/// Additional scale factor, usually
/// 1.0f, but sometimes we want bigger smokes or explosions.
/// Use this rotation
/// Set id
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)
///
/// 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.
///
/// Position
/// Effect type
/// Additional scale factor, usually
/// 1.0f, but sometimes we want bigger smokes or explosions.
/// Use this rotation
/// Set id
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
///
/// Play sound effect, adds 3d sound effect depending on the position.
///
/// Sound type
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);
///
/// 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).
///
/// Start position
/// End position
/// Start position id
/// End position id
/// Show target effects only if
/// we hit something, don't show if shoot goes out of the screen.
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)
///
/// 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).
///
/// Start position
/// End position
/// Start position id
/// End position id
/// Show target effects only if
/// we hit something, don't show if shoot goes out of the screen.
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)
///
/// Update mg effect
///
/// Updated position
/// Id
public static void UpdateMgEffect(Vector3 updatedPos, int id)
{
//foreach (Line line in lines)
for (int num=0; num
/// Update effect
///
/// Updated position
/// Id
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
///
/// Add plasma effect.
/// Shows plasma ball and light effect (both instant only).
///
/// Position
/// Size
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
///
/// Add fire ball effect.
/// Shows fire ball and light effect (both instant only).
/// Also adds small smoke behind fireball (every 1/10 seconds).
///
/// Position
/// Size
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
///
/// 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.
///
/// Position
/// Size
/// Speed of unit per second,
/// very important for determinting how much smoke we should generate.
///
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
///
/// 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).
///
/// Position
/// Size
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)
///
/// Add hit explosion
///
/// Position
/// Size
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
///
/// Add flame explosion for the lizard shoot, high splash value.
///
/// Position
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)
///
/// Add flame explosion for the lizard shoot, high splash value.
///
/// Position
public static void AddFlameExplosion(Vector3 pos)
{
AddFlameExplosion(pos, true);
} // AddFlameExplosion(pos)
#endregion
#endregion
#region Handle all effects
///
/// Handle all effects
///
public void HandleAllEffects()
{
// First draw lines
List linesToRemove = new List();
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 remEffectsToRemove = new List();
//foreach (Effect effect in effects)
for (int num=0; num
/// Effect tests
///
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