diff --git a/DepthsBelow/DepthsBelow/Core.cs b/DepthsBelow/DepthsBelow/Core.cs index fc54e1b..27e7292 100755 --- a/DepthsBelow/DepthsBelow/Core.cs +++ b/DepthsBelow/DepthsBelow/Core.cs @@ -27,7 +27,8 @@ namespace DepthsBelow public EntityManager EntityManager; public TurnManager TurnManager; - public Camera Camera; + public Camera Camera; + public Interface Interface; public static MouseInput MouseInput; public static KeyboardInput KeyboardInput; @@ -71,7 +72,9 @@ namespace DepthsBelow EntityManager = new EntityManager(); TurnManager = new TurnManager(new string[] { "Player", "Computer" }); - Camera = new Camera(this); + Camera = new Camera(this); + Interface = new Interface(this); + Squad = new List(); Swarm = new List(); Volley = new List(); diff --git a/DepthsBelow/DepthsBelow/GUI/Button.cs b/DepthsBelow/DepthsBelow/GUI/Button.cs index a099ff9..0756a89 100755 --- a/DepthsBelow/DepthsBelow/GUI/Button.cs +++ b/DepthsBelow/DepthsBelow/GUI/Button.cs @@ -14,12 +14,12 @@ namespace DepthsBelow.GUI /// public class Button : Frame { - public delegate void OnClickHandler(Point pos); + //public delegate void OnClickHandler(Point pos); /// /// Handler of OnClick events. /// - public OnClickHandler OnClick; + //public OnClickHandler OnClick; private MouseState lastMouseState; @@ -39,7 +39,7 @@ namespace DepthsBelow.GUI { base.Update(gameTime); - MouseState ms = Mouse.GetState(); + /*MouseState ms = Mouse.GetState(); if (ms.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed) { @@ -58,7 +58,7 @@ namespace DepthsBelow.GUI } } - lastMouseState = ms; + lastMouseState = ms;*/ } } } diff --git a/DepthsBelow/DepthsBelow/GUI/Frame.cs b/DepthsBelow/DepthsBelow/GUI/Frame.cs index 9cac473..9c0e47e 100755 --- a/DepthsBelow/DepthsBelow/GUI/Frame.cs +++ b/DepthsBelow/DepthsBelow/GUI/Frame.cs @@ -5,6 +5,7 @@ using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; namespace DepthsBelow.GUI { @@ -46,6 +47,34 @@ namespace DepthsBelow.GUI get { return this.Rectangle.Y; } set { this.Rectangle.Y = value; } } + /// + /// The x-coordinate of the left side of the frame. + /// + public int Left + { + get { return this.Rectangle.Left; } + } + /// + /// The y-coordinate of the top side of the frame. + /// + public int Top + { + get { return this.Rectangle.Top; } + } + /// + /// The x-coordinate of the right side of the frame. + /// + public int Right + { + get { return this.Rectangle.Right; } + } + /// + /// The y-coordinate of the bottom side of the frame. + /// + public int Bottom + { + get { return this.Rectangle.Bottom; } + } /// /// Rectangle of the frame. @@ -77,6 +106,23 @@ namespace DepthsBelow.GUI /// public bool Visible = true; + /// + /// The layer of the frame. + /// Bigger number means closer to the screen. + /// + public int Layer = 0; + /// + /// Gets the sum of this frame and all parent layers. + /// + public int LayerSum + { + get { return (Parent != null) ? this.Layer + Parent.LayerSum : this.Layer; } + } + + /// + /// The unique identifier of the frame. + /// + public int UID { get; private set; } /// /// Potential parent frame. /// @@ -84,7 +130,46 @@ namespace DepthsBelow.GUI /// /// Potential children frames. /// - public List Children; + public List Children; + + #region Events + /// + /// Occurs when the frame is clicked inside it's bounding rectangle. + /// + public event OnClickHandler OnClick; + /// + /// event arguments. + /// + public class OnClickArgs : EventArgs + { + /// + /// The position of the click relative to the frame position. + /// + public Point Position; + + /// + /// The time of the click, since the start of the program. + /// + public TimeSpan Time; + } + /// + /// Handler for click events. + /// + /// The clicked frame. + /// The instance containing the event data. + public delegate void OnClickHandler(Frame frame, OnClickArgs e); + /// + /// Raise an event on the frame. + /// + /// The instance containing the event data. + public void Click(OnClickArgs e) + { + if (OnClick != null) + OnClick(this, e); + } + #endregion + + private MouseState lastMouseState; /// /// Create a blank frame. @@ -97,7 +182,7 @@ namespace DepthsBelow.GUI this.Children = new List(); - GUIManager.Add(this); + UID = GUIManager.Add(this); } /// @@ -153,6 +238,31 @@ namespace DepthsBelow.GUI public virtual void Update(GameTime gameTime) { + /*MouseState ms = Mouse.GetState(); + + if (ms.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed) + { + // HACK: This should be handled globally somewhere else to prevent event bubbling + if ( + ms.X >= AbsoluteRectangle.Left + && ms.X < AbsoluteRectangle.Right + && ms.Y >= AbsoluteRectangle.Top + && ms.Y < AbsoluteRectangle.Bottom) + { + if (OnClick != null) + { + var args = new OnClickArgs() + { + Position = new Point(ms.X - AbsoluteRectangle.X, ms.Y - AbsoluteRectangle.Y), + Time = gameTime.TotalGameTime + }; + OnClick(this, args); + } + } + } + + lastMouseState = ms;*/ + foreach (var child in Children) child.Update(gameTime); } diff --git a/DepthsBelow/DepthsBelow/GUIManager.cs b/DepthsBelow/DepthsBelow/GUIManager.cs index e2e6d79..c95de15 100755 --- a/DepthsBelow/DepthsBelow/GUIManager.cs +++ b/DepthsBelow/DepthsBelow/GUIManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -10,11 +11,13 @@ namespace DepthsBelow { static class GUIManager { - public static List Frames = new List(); + public static List Frames = new List(); + private static int uidIndex = 0; - public static void Add(Frame frame) + public static int Add(Frame frame) { Frames.Add(frame); + return uidIndex++; } public static void Remove(Frame frame) @@ -22,6 +25,47 @@ namespace DepthsBelow Frames.Remove(frame); } + public static void Click(Point position, TimeSpan time) + { + var clickRectangle = new Rectangle(position.X, position.Y, 1, 1); + + var intersections = new List(); + + foreach (var frame in Frames) + { + if (clickRectangle.Intersects(frame.AbsoluteRectangle)) + intersections.Add(frame); + } + + var topFrame = GetTopFrame(intersections); + + if (topFrame != null) + { + var e = new Frame.OnClickArgs() + { + Position = position, + Time = time + }; + topFrame.Click(e); + } + } + + /// + /// Gets the top frame in the frame stack. + /// + /// A list of frames to check. + /// Returns the topmost frame. + private static Frame GetTopFrame(List frames) + { + if (frames.Count == 0) + return null; + + if (frames.Count == 1) + return frames.First(); + + return frames.OrderByDescending(f => f, new FrameSort()).First(); + } + public static void Update(GameTime gameTime) { foreach (var frame in Frames) @@ -30,8 +74,38 @@ namespace DepthsBelow public static void Draw(SpriteBatch spriteBatch) { - foreach (var frame in Frames) + foreach (var frame in Frames.OrderBy(f => f, new FrameSort())) frame.Draw(spriteBatch); } + + /// + /// Sort frames based on layer, using UID as tie breaker. + /// + private class FrameSort : IComparer + { + public int Compare(Frame a, Frame b) + { + var aLayerSum = a.LayerSum; + var bLayerSum = b.LayerSum; + + // Compare the layer sum + if (aLayerSum > bLayerSum) + return 1; + if (aLayerSum < bLayerSum) + return -1; + + // If the result is indecisive, pick the frame with the biggest UID + if (aLayerSum == bLayerSum) + { + if (a.UID > b.UID) + return 1; + + if (a.UID < b.UID) + return -1; + } + + return 0; + } + } } } diff --git a/DepthsBelow/DepthsBelow/Interface.cs b/DepthsBelow/DepthsBelow/Interface.cs index 48093e0..808cab3 100755 --- a/DepthsBelow/DepthsBelow/Interface.cs +++ b/DepthsBelow/DepthsBelow/Interface.cs @@ -2,13 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using DepthsBelow.GUI; using Microsoft.Xna.Framework; using System.Diagnostics; using Microsoft.Xna.Framework.Graphics; namespace DepthsBelow { - class Interface + public class Interface { Core core; @@ -36,6 +37,126 @@ namespace DepthsBelow var text = new GUI.Text(frame); text.SetFont("Arial"); text.Value = "Hello world!";*/ + + // Create some unit frames + + /*var panicFrame = CreatePanicFrame(); + var unit1 = CreateUnitFrame("Flight captain Rainbow"); + unit1.X = panicFrame.X; + unit1.Y = panicFrame.Y + panicFrame.Height; + unit1.OnClick += delegate(Frame frame, Frame.OnClickArgs args) + { + frame.Color = Color.Red; + }; + var unit2 = CreateUnitFrame("Mr. Sparkle"); + unit2.X = unit1.X; + unit2.Y = unit1.Y + unit1.Height; + unit2.OnClick += delegate(Frame frame, Frame.OnClickArgs args) + { + frame.Color = Color.Red; + };*/ + + var frame1 = new GUI.Frame(); + frame1.Layer = 0; + frame1.SetTexture("images/Enter"); + frame1.Color = Color.Red; + frame1.Width = 100; + frame1.Height = 100; + frame1.OnClick += delegate(Frame frame, Frame.OnClickArgs args) + { + if (frame.Color == Color.Red) + frame.Color = Color.Green; + else + frame.Color = Color.Red; + }; + var frame1_child = new GUI.Frame(frame1); + frame1_child.SetTexture("images/Enter"); + frame1_child.Color = Color.Purple; + frame1_child.Width = 60; + frame1_child.Height = 60; + frame1_child.X = 20; + frame1_child.Y = 20; + frame1_child.OnClick += delegate(Frame frame, Frame.OnClickArgs args) + { + if (frame.Color == Color.Purple) + frame.Color = Color.Pink; + else + frame.Color = Color.Purple; + }; + + var frame2 = new GUI.Frame(); + frame2.Layer = 0; + frame2.SetTexture("images/Enter"); + frame2.Color = Color.Blue; + frame2.Width = 100; + frame2.Height = 100; + frame2.X = 50; + frame2.Y = 50; + frame2.OnClick += delegate(Frame frame, Frame.OnClickArgs args) + { + if (frame.Color == Color.Blue) + frame.Color = Color.Yellow; + else + frame.Color = Color.Blue; + }; + } + + private GUI.Frame CreatePanicFrame() + { + var frame = new GUI.Frame(); + frame.SetTexture("images/GUI/unit_background"); + frame.Color = Color.Black; + frame.Width = 164; + frame.Height = 19; + + var healthBg = new GUI.Frame(frame); + healthBg.SetTexture("images/GUI/health_background"); + healthBg.Width = 136; + healthBg.Height = 13; + healthBg.X = 3; + healthBg.Y = 3; + + var healthBar = new GUI.Frame(healthBg); + healthBar.SetTexture("images/GUI/bar_solid"); + healthBar.Color = new Color(87, 55, 253); + healthBar.Width = (int)(healthBg.Width * 0.5); + healthBar.Height = 11; + healthBar.X = 1; + healthBar.Y = 1; + + return frame; + } + + private GUI.Frame CreateUnitFrame(string unitName) + { + var frame = new GUI.Frame(); + frame.SetTexture("images/GUI/unit_background"); + frame.Color = Color.Black; + frame.Width = 164; + frame.Height = 35; + + var nameText = new GUI.Text(frame); + nameText.SetFont("fonts/UnitName"); + nameText.Value = unitName; + nameText.X = 4; + nameText.Y = 1; + + var healthBg = new GUI.Frame(frame); + healthBg.SetTexture("images/GUI/health_background"); + healthBg.Width = 136; + healthBg.Height = 13; + healthBg.X = 3; + healthBg.Y = 19; + + var healthBar = new GUI.Frame(healthBg); + healthBar.SetTexture("images/GUI/bar_solid"); + healthBar.Color = Color.Red; + healthBar.Width = (int)(healthBg.Width * 0.5f); + healthBar.Height = 11; + healthBar.X = 1; + healthBar.Y = 1; + + return frame; } } } diff --git a/DepthsBelow/DepthsBelow/KeyboardInput.cs b/DepthsBelow/DepthsBelow/KeyboardInput.cs index 01882d9..02818da 100644 --- a/DepthsBelow/DepthsBelow/KeyboardInput.cs +++ b/DepthsBelow/DepthsBelow/KeyboardInput.cs @@ -26,6 +26,13 @@ namespace DepthsBelow { KeyboardState ks = Keyboard.GetState(); + // Lua reload scripts + if (ks.IsKeyUp(Keys.R) && lastKeyboardState.IsKeyDown(Keys.R)) + { + core.Lua.Reload(); + } + + // Next turn if (ks.IsKeyDown(Keys.Enter) && lastKeyboardState.IsKeyUp(Keys.Enter)) { if (core.TurnManager.CurrentTurn == core.TurnManager["Player"]) diff --git a/DepthsBelow/DepthsBelow/Lua.cs b/DepthsBelow/DepthsBelow/Lua.cs index 618636f..50716ce 100755 --- a/DepthsBelow/DepthsBelow/Lua.cs +++ b/DepthsBelow/DepthsBelow/Lua.cs @@ -53,10 +53,12 @@ namespace DepthsBelow { private LuaInterface.Lua lua; + private List filesToRun; + public Lua() { - ResetContext(); - ExposeLibraries(); + filesToRun = new List(); + Initialize(); /*lua.DoString(@" local frame = CreateFrame('Frame'); @@ -71,6 +73,15 @@ namespace DepthsBelow ");*/ } + private void Initialize() + { + if (lua == null) + { + lua = new LuaInterface.Lua(); + ExposeLibraries(); + } + } + public void ExposeLibraries() { lua.NewTable("Console"); @@ -120,7 +131,13 @@ namespace DepthsBelow if (lua != null) lua.Dispose(); - lua = new LuaInterface.Lua(); + Initialize(); + } + + public void Reload() + { + ResetContext(); + LoadScripts(); } public void LoadScripts() @@ -128,7 +145,7 @@ namespace DepthsBelow // Load scripts from script folder // HACK: This needs to load files on the fly instead of loading precompiled files by the content manager. // http://xbox.create.msdn.com/en-US/education/catalog/sample/winforms_series_2 maybe? - var scripts = GameServices.GetService().LoadContent("scripts"); + /*var scripts = GameServices.GetService().LoadContent("scripts"); foreach (var script in scripts) { try @@ -140,9 +157,19 @@ namespace DepthsBelow Console.WriteLine("Lua error: " + e.Message); } + }*/ + + foreach (var fileName in filesToRun) + { + lua.DoFile(GameServices.GetService().RootDirectory + "/" + fileName); } } + public void AddFile(string fileName) + { + filesToRun.Add(fileName); + } + public T GetObject(string obj) { return (T)lua[obj]; diff --git a/DepthsBelow/DepthsBelow/MouseInput.cs b/DepthsBelow/DepthsBelow/MouseInput.cs index de6140c..553eab5 100755 --- a/DepthsBelow/DepthsBelow/MouseInput.cs +++ b/DepthsBelow/DepthsBelow/MouseInput.cs @@ -43,6 +43,11 @@ namespace DepthsBelow gridTexture.SetData(new Color[] { Color.White }); } + public void OnClick(MouseState ms, GameTime gameTime) + { + GUIManager.Click(new Point(ms.X, ms.Y), gameTime.TotalGameTime); + } + public void Update(GameTime gameTime) { MouseState ms = Mouse.GetState(); @@ -50,6 +55,14 @@ namespace DepthsBelow Rectangle mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); KeyboardState ks = Keyboard.GetState(); + // OnClick event + if ( + (ms.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed) + || (ms.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed) + ) + OnClick(ms, gameTime); + + // Tooltip stuff var tooltip = core.Lua.GetObject("ToolTip"); if (tooltip != null) diff --git a/DepthsBelow/DepthsBelowContent/DepthsBelowContent.contentproj b/DepthsBelow/DepthsBelowContent/DepthsBelowContent.contentproj index 68b9f15..082baf3 100755 --- a/DepthsBelow/DepthsBelowContent/DepthsBelowContent.contentproj +++ b/DepthsBelow/DepthsBelowContent/DepthsBelowContent.contentproj @@ -139,16 +139,48 @@ gui LuaImporter + Always test LuaImporter + Always tooltip LuaImporter + Always + + + + + bar_solid + TextureImporter + TextureProcessor + + + bar_transparent + TextureImporter + TextureProcessor + + + health_background + TextureImporter + TextureProcessor + + + unit_background + TextureImporter + TextureProcessor + + + + + UnitName + FontDescriptionImporter + FontDescriptionProcessor diff --git a/DepthsBelow/DepthsBelowContent/fonts/UnitName.spritefont b/DepthsBelow/DepthsBelowContent/fonts/UnitName.spritefont new file mode 100755 index 0000000..cafaa2e --- /dev/null +++ b/DepthsBelow/DepthsBelowContent/fonts/UnitName.spritefont @@ -0,0 +1,60 @@ + + + + + + + Arial + + + 10 + + + 0 + + + true + + + + + + + + + + + + ~ + + + + diff --git a/DepthsBelow/DepthsBelowContent/images/GUI/bar_solid.png b/DepthsBelow/DepthsBelowContent/images/GUI/bar_solid.png new file mode 100755 index 0000000..383a4c9 Binary files /dev/null and b/DepthsBelow/DepthsBelowContent/images/GUI/bar_solid.png differ diff --git a/DepthsBelow/DepthsBelowContent/images/GUI/bar_transparent.png b/DepthsBelow/DepthsBelowContent/images/GUI/bar_transparent.png new file mode 100755 index 0000000..c491c5e Binary files /dev/null and b/DepthsBelow/DepthsBelowContent/images/GUI/bar_transparent.png differ diff --git a/DepthsBelow/DepthsBelowContent/images/GUI/health_background.png b/DepthsBelow/DepthsBelowContent/images/GUI/health_background.png new file mode 100755 index 0000000..4f5ca5d Binary files /dev/null and b/DepthsBelow/DepthsBelowContent/images/GUI/health_background.png differ diff --git a/DepthsBelow/DepthsBelowContent/images/GUI/unit_background.png b/DepthsBelow/DepthsBelowContent/images/GUI/unit_background.png new file mode 100755 index 0000000..303465a Binary files /dev/null and b/DepthsBelow/DepthsBelowContent/images/GUI/unit_background.png differ diff --git a/DepthsBelow/DepthsBelowContent/scripts/gui.lua b/DepthsBelow/DepthsBelowContent/scripts/gui.lua index f821136..5ce887b 100755 --- a/DepthsBelow/DepthsBelowContent/scripts/gui.lua +++ b/DepthsBelow/DepthsBelowContent/scripts/gui.lua @@ -1,3 +1,6 @@ +luanet.load_assembly("Microsoft.Xna.Framework") +Color = luanet.import_type("Microsoft.Xna.Framework.Color") + local frame = CreateFrame('Frame'); frame.X = 100; @@ -9,3 +12,70 @@ button.OnClick = function(clickPos) Console.WriteLine(clickPos.X .. ' ' .. clickPos.Y) end + +function CreatePanicFrame(x, y) + local frame = CreateFrame("Frame") + frame:SetTexture("images/GUI/unit_background") + frame.Width = 154 + frame.Height = 19 + frame.X = x + frame.Y = y + + local healthBg = CreateFrame("Frame", frame) + healthBg:SetTexture("images/GUI/health_background") + healthBg.Width = 136 + healthBg.Height = 13 + healthBg.X = 3 + healthBg.Y = 3 + + local healthBar = CreateFrame("Frame", healthBg) + healthBar:SetTexture("images/GUI/bar_solid") + healthBar.Color = Color(87, 55, 253) + healthBar.Width = healthBg.Width * 0.5 + healthBar.Height = 11 + healthBar.X = 1 + healthBar.Y = 1 + + return frame +end + +function CreateUnitFrame(name, x, y) + -- Frames for one unit + local frame = CreateFrame("Frame") + frame:SetTexture("images/GUI/unit_background") + frame.Width = 164; + frame.Height = 35; + frame.X = x + frame.Y = y + + local nameText = CreateFrame("Text", frame) + nameText:SetFont("fonts/UnitName") + nameText.Value = name + nameText.X = 4 + nameText.Y = 1 + + local healthBg = CreateFrame("Frame", frame) + healthBg:SetTexture("images/GUI/health_background") + healthBg.Width = 136 + healthBg.Height = 13 + healthBg.X = 3 + healthBg.Y = 19 + + local healthBar = CreateFrame("Frame", healthBg) + healthBar:SetTexture("images/GUI/bar_solid") + healthBar.Color = Color.Red + healthBar.Width = healthBg.Width * 0.5 + healthBar.Height = 11 + healthBar.X = 1 + healthBar.Y = 1 + + return frame +end + +--[[local frame; +frame = CreatePanicFrame(0, 0) +frame = CreateUnitFrame("Flight captain Rainbow Dash", frame.X, frame.Y + frame.Height) +CreateUnitFrame("Mr. Sparkle", frame.X, frame.Y + frame.Height)]]-- + +local testFrame = CreateTestFrame() +testFrame:SetWidth(1337) \ No newline at end of file