//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynterEngine.UserInterface { #region Using Statements using System; using System.Collections.Generic; using System.Collections; 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 Globals; #endregion /// /// Creates, updates, and draws a heads up display on the user's viewport. /// public class HeadsUpDisplay { // Attributes: // Screen dead zone percentage private const float SIDES_DEAD_ZONE_PERCENT = 0.05f; private const float TOP_BOTTOM_DEAD_ZONE_PERCENT = 0.03f; private int playerIndex = 0; /// /// View-port on which our HUD will draw itself /// public Viewport parentViewport; // List of Text Displays private List textDisplays = new List(); // List of Value Displays private List valueDisplays = new List(); // List of Image Displays private List imageDisplays = new List(); private List imageSpinners = new List(); /// /// Indicates what type of Heads Up Display element this is. /// public enum DisplayType { /// /// A string of text. /// TEXT, /// /// A numerical value. /// VALUE, /// /// An image. /// IMAGE, /// /// Default. /// BASE }; /// /// Base class for all types. /// public class HUDDisplay { /// /// Text string drawn to HUD. /// public string text; /// /// Position of HUD element. /// public Vector2 position = new Vector2(); /// /// Width of HUD element. /// public int width; /// /// Height of HUD element. /// public int height; /// /// Color of text element. /// public Color color; /// /// Type of HUD element. /// public DisplayType type = DisplayType.BASE; /// /// Visibility of HUD element. /// public bool visible = true; }; /// /// Used to display Text. /// private class TextDisplay : HUDDisplay { /// /// Text display constructor. /// public TextDisplay() { type = DisplayType.TEXT; } } /// /// Used to display Values. /// private class ValueDisplay : HUDDisplay { /// /// Numerical value drawn to HUD. /// public float value; /// /// Value display constructor. /// public ValueDisplay() { type = DisplayType.VALUE; } } /// /// Used to display Images. /// public class ImageDisplay : HUDDisplay { /// /// Image drawn to HUD. /// public Texture2D image; /// /// X scale of image. /// public float xScale; /// /// Y scale of image. /// public float yScale; /// /// Image display constructor. /// Scale defaults to 1. /// public ImageDisplay() { xScale = 1.0f; yScale = 1.0f; type = DisplayType.IMAGE; } } /// /// Used to display image sequences /// public class ImageSpinner : HUDDisplay { /// /// Array of images /// public ImageDisplay[] images; /// /// Index of active image /// public int activeIndex; /// /// Constructor /// /// Size of Image Display public ImageSpinner(int size) { this.activeIndex = 0; this.images = new ImageDisplay[size]; } /// /// Add an image to our array /// /// Image /// Location public void addImage(ImageDisplay val, int slot) { images[slot] = val; } /// /// Iterate to next image /// public void next() { if (this.images.Length <= this.activeIndex + 1) { this.activeIndex = 0; } else { this.activeIndex++; } } /// /// Iterate to previous image /// public void prev() { if (this.activeIndex == 0) { this.activeIndex = this.images.Length - 1; } else { this.activeIndex--; } } } /// /// Heads Up Display constructor. /// public HeadsUpDisplay() { playerIndex = 0; } /// /// Heads Up Display constructor with player index and predefined viewport. /// /// Player this HUD belongs to. /// Player's viewport. public HeadsUpDisplay(int index, Viewport viewport) { playerIndex = index; parentViewport = viewport; } // Methods: //******************************************************************************************* // Still buggy.. I need to come back to it later // Check for edges of the screen if playing on Xbox360 private void AdjustForDeadZone(HUDDisplay element) { #if false//XBOX360 float deadZoneX = Statics.GAME_WINDOW_WIDTH * SIDES_DEAD_ZONE_PERCENT; float deadZoneY = Statics.GAME_WINDOW_HEIGHT * TOP_BOTTOM_DEAD_ZONE_PERCENT; Vector2 absolutePosition = Vector2.Zero + element.position; // Player 1 always in absolute coordinates // Check Player 2: if (playerIndex == 1) { if (Statics.TOTAL_PLAYERS_PLAYING == 2) { absolutePosition += new Vector2(0, parentViewport.Height); } else { absolutePosition += new Vector2(parentViewport.Width, 0); } } else if (playerIndex == 2) { absolutePosition += new Vector2(0, parentViewport.Height); } else if (playerIndex == 3) { absolutePosition += new Vector2(parentViewport.Width, parentViewport.Height); } // First check for the left side dead zone // If its on the left side if (absolutePosition.X < Statics.GAME_WINDOW_WIDTH * 0.5f) { if (playerIndex == 0 || (playerIndex == 1 && Statics.TOTAL_PLAYERS_PLAYING == 2) || (playerIndex == 2 && Statics.TOTAL_PLAYERS_PLAYING > 2)) { element.position.X += deadZoneX; } } // else.. check for right side else if (absolutePosition.X > Statics.GAME_WINDOW_WIDTH * 0.5f) { if (playerIndex == 1 || (playerIndex == 0 && Statics.TOTAL_PLAYERS_PLAYING <= 2) || playerIndex == 3) { element.position.X -= deadZoneX; } } // Then check upper side if (absolutePosition.Y < Statics.GAME_WINDOW_HEIGHT * 0.5f) { if (playerIndex == 0 || (playerIndex == 1 && Statics.TOTAL_PLAYERS_PLAYING > 2)) { element.position.Y += deadZoneY; } } else if (absolutePosition.Y > Statics.GAME_WINDOW_HEIGHT * 0.5f) { if (playerIndex == 2 || playerIndex == 3 || (playerIndex == 0 && Statics.TOTAL_PLAYERS_PLAYING == 1) || (playerIndex == 1 && Statics.TOTAL_PLAYERS_PLAYING == 2)) { element.position.Y -= deadZoneY; } } #endif } /// /// Add a Text display to the TextDisplay list. /// /// Text to add. /// Position to locate text. /// Color to display text with. /// Count of text displays public int AddTextDisplay(string text, Vector2 position, Color color) { TextDisplay temp = new TextDisplay(); temp.text = text; Vector2 size = FontWriter.Arial.MeasureString(text); temp.width = (int)(size.X); temp.height = (int)(size.Y); temp.position = position; AdjustForDeadZone(temp); temp.color = color; textDisplays.Add(temp); return textDisplays.Count - 1; } /// /// Add a Value display to the ValueDisplay list. /// /// Text to display. /// Value to display. /// Position to display value. /// Width of value display. /// Height of value display. /// Color of value and text. /// Count of value displays public int AddValueDisplay(string text, float value, Vector2 position, int width, int height, Color color) { ValueDisplay temp = new ValueDisplay(); temp.text = text; temp.value = value; temp.width = width; temp.height = height; temp.position = position; AdjustForDeadZone(temp); temp.color = color; valueDisplays.Add(temp); return valueDisplays.Count - 1; } /// /// Add an Image display to our ImageDisplay list. /// /// Image to display. /// Position to display value. /// Width of value display. /// Height of value display. /// Color of value and text. /// Toggle to turn drawing on/off. /// Count of image displays public int AddImageDisplay(Texture2D image, Vector2 position, int width, int height, Color color, bool draw) { ImageDisplay temp = new ImageDisplay(); temp.image = image; temp.width = width; temp.height = height; temp.position = position; AdjustForDeadZone(temp); temp.color = color; temp.visible = draw; imageDisplays.Add(temp); return imageDisplays.Count - 1; } /// /// Add an Image spinner to our ImageDisplay list /// /// Image spinner to add /// Count of image spinners public int AddImageSpinner(ImageSpinner val) { this.imageSpinners.Add(val); return imageSpinners.Count - 1; } /// /// Set the image spinner at index location to the next in-line /// /// location public void SpinnerNext(int index) { if (index < 0 || index >= this.imageSpinners.Count) { // Invalid index return; } else { ImageSpinner temp = this.imageSpinners[index]; temp.next(); this.imageSpinners[index] = temp; } } /// /// Set the image spinner at index location to the previous inline /// /// location public void SpinnerBack(int index) { if (index < 0 || index >= this.imageSpinners.Count) { // Invalid index return; } else { ImageSpinner temp = this.imageSpinners[index]; temp.prev(); this.imageSpinners[index] = temp; } } /// /// Set the active index to val in our image spinner at index /// /// location /// Active value public void SpinnerSet(int index, int val) { if (index < 0 || index >= this.imageSpinners.Count) { // Invalid index return; } ImageSpinner temp = this.imageSpinners[index]; if (val < 0 || temp.images.Length <= val) { return; } else { temp.activeIndex = val; this.imageSpinners[index] = temp; } } /// /// Method which allows us to change the text in a TextDisplay /// /// location /// New text public void UpdateText(int index, string newText) { if (index < 0 || index >= textDisplays.Count) { // Invalid index return; } else { // Change the text textDisplays[index].text = newText; } } /// /// Updates the visibility of a text display /// /// location /// New text /// Visibility /// Display color public void UpdateTextVis(int index, string newText, bool vis, Color color) { if (index < 0 || index >= textDisplays.Count) { // Invalid index return; } else { // Change the text textDisplays[index].color = color; textDisplays[index].text = newText; textDisplays[index].visible = vis; } } /// /// Method which allows us to change the Value in a ValueDisplay. /// /// Location of ValueDisplay in list. /// New value of value display. public void UpdateValue(int index, float newValue) { if (index < 0 || index >= valueDisplays.Count) { // Invalid index return; } else { // Change the value valueDisplays[index].value = newValue; } } /// /// Updates the x and y scale of an image display /// /// Location of ValueDisplay in list. /// X-scale value. /// Y-scale value. public void UpdateImageScale(int index, float xScale, float yScale) { if (index < 0 || index >= this.imageDisplays.Count) { // Invalid index return; } else { this.imageDisplays[index].xScale = xScale; this.imageDisplays[index].yScale = yScale; } } /// /// Change height of an image. /// /// Location of ValueDisplay in list. /// New height of Image.. public void UpdateImageHeight(int index, int amount) { if (index < 0 || index >= this.imageDisplays.Count) { // Invalid index return; } else { this.imageDisplays[index].height = amount; } } /// /// Chage position of image. /// /// Location of ValueDisplay in list. /// New position of image. public void UpdateImagePosition(int index, Vector2 newPosition) { if (index < 0 || index >= this.imageDisplays.Count) { // Invalid index return; } else { this.imageDisplays[index].position = newPosition; } } /// /// Change whether image is drawn of not. /// /// Location of ValueDisplay in list. /// True to draw image, false to hide. public void UpdateImageDraw(int index, bool value) { if (index < 0 || index >= this.imageDisplays.Count) { // Invalid index return; } else { this.imageDisplays[index].visible = value; } } /// /// Method that sets a text display as visible or invisible. /// /// Location of ValueDisplay in list. /// True to draw image, false to hide. public void UpdateTextVisible(int index, bool visible) { if (index < 0 || index >= textDisplays.Count) { // Invalid index return; } else { // Change the value textDisplays[index].visible = visible; } } /// /// Method which allows us to change the color of a TextDisplay. /// /// Location of ValueDisplay in list. /// New color of text. public void UpdateTextColor(int index, Color color) { if (index < 0 || index >= textDisplays.Count) { // Invalid index return; } else { // Change the value textDisplays[index].color = color; } } /// /// Default Draw function. /// /// SpriteBatch used to draw used to draw. public void Draw(SpriteBatch spriteBatch) { Draw(spriteBatch, 0, 0); } /// /// Draw function for drawing our displays at a certain offset position. /// NOTE: SpriteBatch Begin and End are handled outside this scope. /// /// SpriteBatch used to draw used to draw. /// X-Offset to draw location. /// Y-Offset to draw location. public void Draw(SpriteBatch spriteBatch, int xoffset, int yoffset) { foreach (TextDisplay element in textDisplays) { if (element.visible) { spriteBatch.DrawString(FontWriter.Arial, element.text, element.position, element.color); } } foreach (ImageDisplay element in imageDisplays) { if (element.visible == true) { spriteBatch.Draw(element.image, new Rectangle((int)element.position.X + xoffset, (int)element.position.Y + yoffset, element.width, element.height), new Rectangle(0, 0, (int)(element.image.Width * element.xScale), (int)(element.image.Height * element.yScale)), element.color); } } foreach (ImageSpinner elementBig in imageSpinners) { if (elementBig.visible == true) { ImageDisplay element = elementBig.images[elementBig.activeIndex]; spriteBatch.Draw(element.image, new Rectangle((int)element.position.X + xoffset, (int)element.position.Y + yoffset, element.width, element.height), new Rectangle(0, 0, (int)(element.image.Width * element.xScale), (int)(element.image.Height * element.yScale)), element.color); } } } } }