// 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