//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynterEngine.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; #endregion using Globals; using ObjectLib; using UserInterface; using GameObjects; using Controllers; /// /// 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.ObjectType.PLAYER; mass.gameObjectPointer = this; } //public Human(int playerNumber) // : base(playerNumber) //{ // rumbleEventList.Clear(); // mass.objectType = Enums.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.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 the rumble if (DarkWynterGame.playerController.gameInput.attack != 0) { float left = 0; float right = 0; // If terrain mod switch is on OR there are no elements selected if (DarkWynterGame.playerController.gameInput.attackMode == Enums.AttackMode.TERRAIN_MOD) { if (DarkWynterGame.playerController.gameInput.defendAmount > 0.0f) { left = 0.4f; } if (DarkWynterGame.playerController.gameInput.attackAmount > 0.0f) { right = 0.4f; } AddRumble(DarkWynterGame.playerController.gameInput.defendAmount, DarkWynterGame.playerController.gameInput.attackAmount, 150); } else { if (DarkWynterGame.playerController.gameInput.defendAmount > 0.0f) { left = 0.1f; } if (DarkWynterGame.playerController.gameInput.attackAmount > 0.0f) { right = 0.2f; } AddRumble(left, right, 100); } } // Update HUD UpdateHUD(); UpdateRumble(); base.Update(ref objectLibrary); } private void UpdateRumble() { if (DarkWynterGame.playerController.playerControllerType == Enums.ControllerType.PC_ONLY) { return; } if (IsAlive() == false) { GamePad.SetVibration(DarkWynterGame.playerController.playerControllerIndex, 0, 0); return; } // Check if time has run out if (stopAllRumble.ElapsedMilliseconds >= STOP_ALL_RUMBLETIME_MILLI) { GamePad.SetVibration(DarkWynterGame.playerController.playerControllerIndex, 0, 0); rumbleEventList.Clear(); } // Check current state if (hitWhere.Contains(Enums.HitWhere.LEFT)) { AddRumble(0.5f, 0.0f, 50); } else if (hitWhere.Contains(Enums.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.playerController.playerControllerIndex, leftRumbleAmount, rightRumbleAmount); // Remove from the list rumbleEventList.RemoveAt(i); i--; } } hitWhere.Clear(); } private void AddRumble(float left, float right, int duration) { if (DarkWynterGame.playerController.playerControllerType == Enums.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.playerController.playerControllerIndex, leftRumbleAmount, rightRumbleAmount); // Start global rumble timer stopAllRumble = Stopwatch.StartNew(); } /// /// Displays which player kills the current player /// /// Player name public void SetKilledByInfo(string s) { deadHUD.UpdateText(this.dhudKilledByIndex, s); } /// /// Displays if a player was killed by a particle /// /// Killer particle public void SetKilledByInfo(Particle particle) { 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 (particle.particleType) { case Enums.ParticleType.Air: deadHUD.UpdateText(this.dhudKilledByIndex, "Blown away by " + killerString); break; case Enums.ParticleType.Earth: if (particle.mass.energy > 0.3f) { deadHUD.UpdateText(this.dhudKilledByIndex, "Molted by " + killerString); } else { deadHUD.UpdateText(this.dhudKilledByIndex, "Buried by " + killerString); } break; case Enums.ParticleType.Water: if (particle.mass.energy > 0.3f) { deadHUD.UpdateText(this.dhudKilledByIndex, "Boiled by " + killerString); } else if (particle.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.LevelSettings.gameTimer.Elapsed.TotalSeconds) % 60; int minutes = ((int)Statics.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.MovementType.WALK) { HUD.UpdateText(this.hudMovementType, "Move: Walk"); } else { HUD.UpdateText(this.hudMovementType, "Move: Hover"); } if (airElementSelected) { HUD.SpinnerSet(this.mainSpinner, 3); } if (waterElementSelected) { HUD.SpinnerSet(this.mainSpinner, 2); } if (earthElementSelected) { HUD.SpinnerSet(this.mainSpinner, 0); } if (fireElementSelected) { HUD.SpinnerSet(this.mainSpinner, 1); } if (terrainModEnabled) { 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.RenderSettings.GAME_WINDOW_WIDTH); sizeRatioH = ((float)viewport.Height / (float)Statics.RenderSettings.GAME_WINDOW_HEIGHT); float scaleX = (Statics.RenderSettings.GAME_WINDOW_WIDTH / 1280.0f); float scaleY = (Statics.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.SystemSettings.content.Load("Content/_textures/box_sides_small"); borderTexture_top = Statics.SystemSettings.content.Load("Content/_textures/box_top_small"); // Also add the manna gain indicator (blue) hudMannaGainIndicator = HUD.AddImageDisplay(Statics.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.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.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.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.SystemSettings.graphics.GraphicsDevice.PresentationParameters.BackBufferHeight && objectLibrary.gpuObjectLists[0].locationMap._write.Width < Statics.SystemSettings.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.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.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.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.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.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.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.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.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.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.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.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.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.playerController.playerControllerIndex, 0.0f, 0.0f); } } }