//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Game.GameObjects { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Diagnostics; using System.Threading; using DarkWynter.Engine; using DarkWynter.Engine.Globals; using DarkWynter.Engine.ObjectLib; using DarkWynter.Engine.GameObjects; using DarkWynter.Engine.Controllers; using DarkWynter.Engine.UserInterface; using DarkWynter.Stream; #endregion /// /// Child class of player which handles human interactions with the game /// public class Human : Player { /// /// Heads up display /// public HeadsUpDisplay HUD = new HeadsUpDisplay(); /// /// HUDs which can be removed /// public HeadsUpDisplay deadHUD = new HeadsUpDisplay(); private float sizeRatioH; private float sizeRatioW; private int hudDamageIndicator; private int hudMannaGainIndicator; private int hudKeyIndicator; private int hudMovementType; private int hudWeaponSelect; private int plungerMana; private int plungerHealth; private int hudTargetIndex; private int hudKillsIndex; private int mainSpinner; private int hudKeysIndex; private int keysCollected; private int dhudKilledByIndex; private int hudDPadGlyph; private int hudDPadRetical; private int width; private int manaIndex; private int healthIndex; private int hudGameTimer; private int hudLocationMap; private string timing; private Texture2D borderTexture_top; private Texture2D borderTexture_side; /// /// Should this controller rumble? /// public bool rumbleEnabled = true; // Update Rumble Pack private float leftRumbleAmount = 0.0f; private float rightRumbleAmount = 0.0f; private List rumbleEventList = new List(); private Stopwatch stopAllRumble = new Stopwatch(); private float MAX_RUMBLE_VALUE = 1.0f; private int STOP_ALL_RUMBLETIME_MILLI = 300; //damage indicator private int DAMAGE_INDICATOR_TIME_MILLI = 500; private Stopwatch damageIndicatorTimer = new Stopwatch(); //manna gain indicator private int MANNA_GAIN_INDICATOR_TIME_MILLI = 500; private Stopwatch mannaIndicatorTimer = new Stopwatch(); // Key indicator private int KEY_INDICATOR_TIME_MILLI = 500; private Stopwatch keyIndicatorTimer = new Stopwatch(); private class RumbleEvent { public float leftRumbleAmount; public float rightRumbleAmount; public int rumbleDuration; public Stopwatch timer; public RumbleEvent() { leftRumbleAmount = 0; rightRumbleAmount = 0; rumbleDuration = 0; timer = new Stopwatch(); } // Activate the rumble for a specified duration the duration is in milliseconds! public void Activate(float left, float right, int duration) { leftRumbleAmount = left; rightRumbleAmount = right; rumbleDuration = duration; timer = Stopwatch.StartNew(); } // Checks to see if we should stop this rumble public bool HasStopped() { if (timer.ElapsedMilliseconds >= rumbleDuration) { return true; } return false; } }; /// /// Constructor /// public Human() : base() { rumbleEventList.Clear(); mass.objectType = Enums_Engine.ObjectType.PLAYER; mass.gameObjectPointer = this; } //public Human(int playerNumber) // : base(playerNumber) //{ // rumbleEventList.Clear(); // mass.objectType = Enums_Engine.ObjectType.PLAYER; // mass.gameObjectPointer = this; //} /// /// Load Human information from XML /// /// Human Node /// ObjectLibrary /// True if load was successful public override bool Load(XmlNode node, ObjectLibrary objectLibrary) { if (!base.Load(node, objectLibrary)) { return false; } StopRumble(); rumbleEventList.Clear(); CreateHUD(Statics_Stream.RenderSettings.cameraList[0].viewport, objectLibrary); return true; } /// /// Update player behavior /// public override void Update(ref ObjectLibrary objectLibrary) { //if (DarkWynterGame.playerController == null) //{ // return; //} //// Get the controller updates //DarkWynterGame.playerController.Update(lastModeSelected); // Update HUD UpdateHUD(); UpdateRumble(); base.Update(ref objectLibrary); UpdateIndicators(); UpdateKillInfo(); if (stopRumble) { StopRumble(); } } /// /// Method for updating the rumble when an attack/defend button is pressed /// protected override void UpdateAttackRumble() { if (GameController.playerControllerType == Enums_Engine.ControllerType.PC_ONLY) { return; } // Update the rumble AddRumble(-attackAmount, attackAmount, 150); } private void UpdateIndicators() { // Check indicators if (damageIndicator) { damageIndicator = false; ShowDamageIndicator(); } if (mannaIndicator) { mannaIndicator = false; ShowMannaIndicator(); } if (keyIndicator) { keyIndicator = false; ShowKeyIndicator(); } } private void UpdateRumble() { if (GameController.playerControllerType == Enums_Engine.ControllerType.PC_ONLY) { return; } if (IsAlive() == false) { GamePad.SetVibration(DarkWynterGame.gameController.playerIndex, 0, 0); return; } // Check if time has run out if (stopAllRumble.ElapsedMilliseconds >= STOP_ALL_RUMBLETIME_MILLI) { GamePad.SetVibration(DarkWynterGame.gameController.playerIndex, 0, 0); rumbleEventList.Clear(); } // Check current state if (hitWhere.Contains(Enums_Engine.HitWhere.LEFT)) { AddRumble(0.5f, 0.0f, 50); } else if (hitWhere.Contains(Enums_Engine.HitWhere.RIGHT)) { AddRumble(0.0f, 0.5f, 50); } // First check to see if any rumble events have ended for (int i = 0; i < rumbleEventList.Count; i++) { if (rumbleEventList[i].HasStopped()) { leftRumbleAmount -= rumbleEventList[i].leftRumbleAmount; rightRumbleAmount -= rumbleEventList[i].rightRumbleAmount; // Apply new rumble amount GamePad.SetVibration(DarkWynterGame.gameController.playerIndex, leftRumbleAmount, rightRumbleAmount); // Remove from the list rumbleEventList.RemoveAt(i); i--; } } hitWhere.Clear(); } private void AddRumble(float left, float right, int duration) { if (GameController.playerControllerType == Enums_Engine.ControllerType.PC_ONLY || rumbleEnabled == false) { return; } if (rumbleEventList.Count >= 5) { // Don't want too many events return; } // Add a new rumble event rumbleEventList.Add(new RumbleEvent()); rumbleEventList[rumbleEventList.Count - 1].Activate(left, right, duration); leftRumbleAmount += left; rightRumbleAmount += right; // Check for max rumble if (leftRumbleAmount > MAX_RUMBLE_VALUE) { leftRumbleAmount = MAX_RUMBLE_VALUE; } if (rightRumbleAmount > MAX_RUMBLE_VALUE) { rightRumbleAmount = MAX_RUMBLE_VALUE; } // Apply new rumble amount GamePad.SetVibration(DarkWynterGame.gameController.playerIndex, leftRumbleAmount, rightRumbleAmount); // Start global rumble timer stopAllRumble = Stopwatch.StartNew(); } /// /// Draw HUD /// /// Sprite Batch public override void DrawHUD(SpriteBatch spriteBatch) { if (IsAlive()) { HUD.Draw(spriteBatch); } else { deadHUD.Draw(spriteBatch); } } /// /// Displays how the current player died /// public void UpdateKillInfo() { if (killInfo != "") { deadHUD.UpdateText(this.dhudKilledByIndex, killInfo); } else if (killingParticle != null) { string killerString; if (killedBy == playerIndex) { deadHUD.UpdateText(this.dhudKilledByIndex, "Suicidal tendencies..."); } else { switch (killedBy) { case 0: killerString = "Player 1"; break; case 1: killerString = "Player 2"; break; case 2: killerString = "Player 3"; break; case 3: killerString = "Player 4"; break; default: killerString = "Bot " + (killedBy - 3); break; } switch (killingParticle.particleType) { case Enums_Engine.ParticleType.Air: deadHUD.UpdateText(this.dhudKilledByIndex, "Blown away by " + killerString); break; case Enums_Engine.ParticleType.Earth: if (killingParticle.mass.energy > 0.3f) { deadHUD.UpdateText(this.dhudKilledByIndex, "Molted by " + killerString); } else { deadHUD.UpdateText(this.dhudKilledByIndex, "Buried by " + killerString); } break; case Enums_Engine.ParticleType.Water: if (killingParticle.mass.energy > 0.3f) { deadHUD.UpdateText(this.dhudKilledByIndex, "Boiled by " + killerString); } else if (killingParticle.mass.energy < -0.3f) { deadHUD.UpdateText(this.dhudKilledByIndex, "Frozen by " + killerString); } else { deadHUD.UpdateText(this.dhudKilledByIndex, "Drowned by " + killerString); } break; } } } } private void UpdateHUD() { if (attackTemperature > 75) { attackTemperature = 75; } if (attackMagnitude > 75) { attackMagnitude = 75; } if (borderTexture_side != null) { int padding = 25; #if XBOX360 padding = 35; #endif //update reticle HUD.UpdateImagePosition(hudDPadRetical, new Vector2(borderTexture_side.Width + (16 + attackTemperature) * sizeRatioH, HUD.parentViewport.Height - padding - (borderTexture_top.Height + attackMagnitude) * sizeRatioH)); //HUD.UpdateImagePosition(this.plungerHealth, new Vector2(width - (100 * sizeRatioH) - borderTexture_side.Width, (200 - (health / 100) * 200) * sizeRatioH)); } int seconds = ((int)Statics_Engine.LevelSettings.gameTimer.Elapsed.TotalSeconds) % 60; int minutes = ((int)Statics_Engine.LevelSettings.gameTimer.Elapsed.TotalSeconds) / 60; string formatedSeconds = seconds.ToString(); if (seconds < 10) { formatedSeconds = "0" + seconds.ToString(); } timing = minutes.ToString() + ":" + formatedSeconds; HUD.UpdateTextVis(this.hudGameTimer, timing, true, Color.Red); HUD.UpdateImageScale(this.healthIndex, 1.0f, health / 100.0f); HUD.UpdateImageScale(this.manaIndex, 1.0f, manna / 100.0f); HUD.UpdateImageHeight(this.healthIndex, (int)(((health / 100) * 200) * sizeRatioH)); HUD.UpdateImageHeight(this.manaIndex, (int)(((manna / 100) * 200) * sizeRatioH)); //Syringe position HUD.UpdateImageHeight(this.plungerHealth, (int)(200 * sizeRatioH - (1 - (health / 100.0f)) * 40 * sizeRatioH)); HUD.UpdateImageHeight(this.plungerMana, (int)(200 * sizeRatioH - (1 - (manna / 100.0f)) * 40 * sizeRatioH)); // Update Keys Element this.keysCollected = this.numberOfKeysFound; HUD.UpdateTextVis(this.hudKeysIndex, "Keys: " + this.keysCollected, true, Color.White); // Update Kills Element HUD.UpdateText(this.hudKillsIndex, "Kills: " + this.kills); if (mass.movementType == Enums_Engine.MovementType.WALK) { HUD.UpdateText(this.hudMovementType, "Move: Walk"); } else { HUD.UpdateText(this.hudMovementType, "Move: Hover"); } if (lastModeSelected == Enums_Engine.AttackType.WIND) { HUD.SpinnerSet(this.mainSpinner, 3); } if (lastModeSelected == Enums_Engine.AttackType.WATER) { HUD.SpinnerSet(this.mainSpinner, 2); } if (lastModeSelected == Enums_Engine.AttackType.EARTH) { HUD.SpinnerSet(this.mainSpinner, 0); } if (lastModeSelected == Enums_Engine.AttackType.FIRE) { HUD.SpinnerSet(this.mainSpinner, 1); } if (lastModeSelected == Enums_Engine.AttackType.TERRAIN) { HUD.SpinnerSet(this.mainSpinner, 4); } //if manna indicator has timed out.. remove it if (mannaIndicatorTimer.ElapsedMilliseconds >= MANNA_GAIN_INDICATOR_TIME_MILLI) { HUD.UpdateImageDraw(this.hudMannaGainIndicator, false); mannaIndicatorTimer.Stop(); mannaIndicatorTimer.Reset(); } //if damage indicator has timed out.. remove it if (damageIndicatorTimer.ElapsedMilliseconds >= DAMAGE_INDICATOR_TIME_MILLI) { HUD.UpdateImageDraw(this.hudDamageIndicator, false); damageIndicatorTimer.Stop(); damageIndicatorTimer.Reset(); } //if damage indicator has timed out.. remove it if (keyIndicatorTimer.ElapsedMilliseconds >= KEY_INDICATOR_TIME_MILLI) { HUD.UpdateImageDraw(this.hudKeyIndicator, false); keyIndicatorTimer.Stop(); keyIndicatorTimer.Reset(); } } /// /// Generate the HUD /// /// Viewport to associate with the HUD /// ObjectLibrary public void CreateHUD(Viewport viewport, ObjectLibrary objectLibrary) { sizeRatioW = ((float)viewport.Width / (float)Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH); sizeRatioH = ((float)viewport.Height / (float)Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT); float scaleX = (Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH / 1280.0f); float scaleY = (Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT / 1024.0f); int spinnerX = (int)(748 * scaleX); int spinnerY = (int)(817 * scaleY); width = viewport.Width; HUD = new HeadsUpDisplay(playerIndex, viewport); deadHUD = new HeadsUpDisplay(playerIndex, viewport); //initialize the HUD for when player is dead... //this is where you put "You were killed by blah..." this.dhudKilledByIndex = deadHUD.AddTextDisplay("", new Vector2(60, 60), Color.Black); //the regular HUD borderTexture_side = Statics_Engine.SystemSettings.content.Load("Content/_textures/box_sides_small"); borderTexture_top = Statics_Engine.SystemSettings.content.Load("Content/_textures/box_top_small"); // Also add the manna gain indicator (blue) hudMannaGainIndicator = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/whitesquare"), new Vector2(0, 0), viewport.Width, viewport.Height, new Color(0, 0, 255, 100), false); // First add the red image for hit effect (red) hudDamageIndicator = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/whitesquare"), new Vector2(0, 0), viewport.Width, viewport.Height, new Color(255, 0, 0, 100), false); // Add the green image for key effect hudKeyIndicator = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/whitesquare"), new Vector2(0, 0), viewport.Width, viewport.Height, new Color(164, 255, 164, 100), false); // HUD background on left side of the screen HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/black"), new Vector2(50, 30), (int)(140), (int)(80), new Color(255, 255, 255, 100), true); // Location Map if (objectLibrary.gpuObjectLists[0].locationMap._write.Height < Statics_Stream.RenderSettings.graphics.GraphicsDevice.PresentationParameters.BackBufferHeight && objectLibrary.gpuObjectLists[0].locationMap._write.Width < Statics_Stream.RenderSettings.graphics.GraphicsDevice.PresentationParameters.BackBufferWidth) { hudLocationMap = HUD.AddImageDisplay(objectLibrary.gpuObjectLists[0].locationMap._write, new Vector2(0, 0), objectLibrary.gpuObjectLists[0].locationMap._write.Width, objectLibrary.gpuObjectLists[0].locationMap._write.Height, new Color(255, 255, 255, 255), true); } // Current Position Map HUD.AddImageDisplay(objectLibrary.gpuObjectLists[0].variables[4]._write, new Vector2(500, 30), objectLibrary.gpuObjectLists[0].variables[4]._write.Width, objectLibrary.gpuObjectLists[0].variables[4]._write.Height, new Color(255, 255, 255, 255), true); this.hudKillsIndex = HUD.AddTextDisplay("Kills:", new Vector2(60, 40), Color.White); this.hudMovementType = HUD.AddTextDisplay("Move: Walk", new Vector2(60, 60), Color.White); this.hudKeysIndex = HUD.AddTextDisplay("Keys: ", new Vector2(60, 80), Color.White); this.hudGameTimer = HUD.AddTextDisplay("Time: ", new Vector2(60, 140), Color.White); HUD.UpdateTextVis(this.hudKeysIndex, "", false, Color.White); // HUD background on right side of the screen HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/black"), new Vector2(viewport.Width - (120 * sizeRatioH) - borderTexture_side.Width, borderTexture_side.Width - 10), (int)(150 * sizeRatioH), (int)(220 * sizeRatioH), new Color(255, 255, 255, 175), true); this.healthIndex = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/Health"), new Vector2(viewport.Width - (100 * sizeRatioH) - borderTexture_side.Width, borderTexture_side.Width), (int)(50 * sizeRatioH), (int)(200 * sizeRatioH), Color.White, true); this.manaIndex = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/Manna"), new Vector2(viewport.Width - (50 * sizeRatioH) - borderTexture_side.Width, borderTexture_side.Width), (int)(50 * sizeRatioH), (int)(200 * sizeRatioH), Color.White, true); int targetSize = 50; hudTargetIndex = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/target"), new Vector2(viewport.Width / 2.0f - (targetSize * 2) / 2, viewport.Height / 2.0f - (targetSize * 2) / 2), (int)(targetSize * 2), (int)(targetSize * 2), Color.White, true); this.hudDPadGlyph = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/DPAD_Glyph"), new Vector2(borderTexture_side.Width, viewport.Height - borderTexture_top.Height - 100 * sizeRatioH), (int)(100 * sizeRatioH), (int)(100 * sizeRatioH), Color.White, true); this.hudDPadRetical = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/DPAD_Target"), new Vector2(borderTexture_side.Width + 16 * sizeRatioH, viewport.Height - 25 - borderTexture_top.Height * sizeRatioH), (int)(10 * sizeRatioH), (int)(10 * sizeRatioH), Color.White, true); HeadsUpDisplay.ImageSpinner spinny = new HeadsUpDisplay.ImageSpinner(4); HeadsUpDisplay.ImageDisplay temp = new HeadsUpDisplay.ImageDisplay(); this.hudWeaponSelect = HUD.AddImageDisplay(Statics_Engine.SystemSettings.content.Load("Content/_textures/wsbg"), new Vector2(viewport.Width - (spinnerX + 2) * sizeRatioW - borderTexture_side.Width, borderTexture_side.Width + (spinnerY - 2) * sizeRatioH + 75), (int)(313 * scaleX * sizeRatioW), (int)(73 * scaleY * sizeRatioW), Color.White, true); //Main bottom spinner temp = new HeadsUpDisplay.ImageDisplay(); spinny = new HeadsUpDisplay.ImageSpinner(5); temp.image = Statics_Engine.SystemSettings.content.Load("Content/_textures/earthHud"); temp.width = (int)(60 * scaleX * sizeRatioW); temp.height = (int)(72 * scaleY * sizeRatioW); temp.position = new Vector2(viewport.Width - spinnerX * sizeRatioW - borderTexture_side.Width, borderTexture_side.Width + spinnerY * sizeRatioH + 75); temp.color = Color.White; temp.visible = true; spinny.visible = true; spinny.addImage(temp, 0); temp = new HeadsUpDisplay.ImageDisplay(); temp.image = Statics_Engine.SystemSettings.content.Load("Content/_textures/fireHud"); temp.width = (int)(60 * scaleX * sizeRatioW); temp.height = (int)(72 * scaleY * sizeRatioW); temp.position = new Vector2(viewport.Width - (spinnerX * sizeRatioW - (temp.width + 2)) - borderTexture_side.Width, borderTexture_side.Width + spinnerY * sizeRatioH + 75); temp.color = Color.White; temp.visible = true; spinny.visible = true; spinny.addImage(temp, 1); temp = new HeadsUpDisplay.ImageDisplay(); temp.image = Statics_Engine.SystemSettings.content.Load("Content/_textures/waterHud"); temp.width = (int)(60 * scaleX * sizeRatioW); temp.height = (int)(72 * scaleY * sizeRatioW); temp.position = new Vector2(viewport.Width - (spinnerX * sizeRatioW - (temp.width + 2) * 2) - borderTexture_side.Width, borderTexture_side.Width + spinnerY * sizeRatioH + 75); temp.color = Color.White; temp.visible = true; spinny.visible = true; spinny.addImage(temp, 2); temp = new HeadsUpDisplay.ImageDisplay(); temp.image = Statics_Engine.SystemSettings.content.Load("Content/_textures/airHud"); temp.width = (int)(60 * scaleX * sizeRatioW); temp.height = (int)(72 * scaleY * sizeRatioW); temp.position = new Vector2(viewport.Width - (spinnerX * sizeRatioW - (temp.width + 2) * 3) - borderTexture_side.Width, borderTexture_side.Width + spinnerY * sizeRatioH + 75); temp.color = Color.White; temp.visible = true; spinny.visible = true; spinny.addImage(temp, 3); temp = new HeadsUpDisplay.ImageDisplay(); ; temp.image = Statics_Engine.SystemSettings.content.Load("Content/_textures/terrainmod"); temp.width = (int)(60 * scaleX * sizeRatioW); temp.height = (int)(72 * scaleY * sizeRatioW); temp.position = new Vector2(viewport.Width - (spinnerX * sizeRatioW - (temp.width + 2) * 4) - borderTexture_side.Width, borderTexture_side.Width + spinnerY * sizeRatioH + 75); temp.color = Color.White; temp.visible = true; spinny.visible = true; spinny.addImage(temp, 4); this.mainSpinner = HUD.AddImageSpinner(spinny); } /// /// Draw the damage indicator /// public void ShowDamageIndicator() { HUD.UpdateImageDraw(this.hudDamageIndicator, true); //reset stopwatch damageIndicatorTimer.Reset(); damageIndicatorTimer.Start(); } /// /// Draw the manna indicator /// public void ShowMannaIndicator() { HUD.UpdateImageDraw(this.hudMannaGainIndicator, true); //reset stopwatch mannaIndicatorTimer.Reset(); mannaIndicatorTimer.Start(); } /// /// Draw the key collected indicator /// public void ShowKeyIndicator() { HUD.UpdateImageDraw(hudKeyIndicator, true); //reset stopwatch keyIndicatorTimer.Reset(); keyIndicatorTimer.Start(); } /// /// Stop all rumbles for this controller /// public void StopRumble() { // Remove all rumble GamePad.SetVibration(DarkWynterGame.gameController.playerIndex, 0.0f, 0.0f); } } }