From d1b3661eed1102fb5bfa4f5be27683b0e19a83b3 Mon Sep 17 00:00:00 2001 From: Niklas Ulf Anders Cullberg Date: Mon, 29 Oct 2012 16:44:59 +0100 Subject: [PATCH] Action Points Movement Perfected --- .../DepthsBelow/Component/PathFinder.cs | 374 +++--- DepthsBelow/DepthsBelow/Interface.cs | 1143 +++++++++-------- DepthsBelow/DepthsBelow/KeyboardInput.cs | 6 +- DepthsBelow/DepthsBelow/Soldier.cs | 22 +- 4 files changed, 786 insertions(+), 759 deletions(-) diff --git a/DepthsBelow/DepthsBelow/Component/PathFinder.cs b/DepthsBelow/DepthsBelow/Component/PathFinder.cs index 381cccf..a0f19c5 100755 --- a/DepthsBelow/DepthsBelow/Component/PathFinder.cs +++ b/DepthsBelow/DepthsBelow/Component/PathFinder.cs @@ -1,183 +1,191 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using AStar; -using Microsoft.Xna.Framework; - -namespace DepthsBelow.Component -{ - /// - /// Component that handles pathfinding. - /// - public class PathFinder : Component - { - /// - /// A pathfinder node. - /// - public class Node - { - /// - /// Grid position of the node. - /// - public Point Position; - /// - /// A* F-score - /// - public int F; - /// - /// A* G-score - /// - public int G; - - /// - /// Explicit conversion between A* library node and Node object. - /// - /// - /// - public static explicit operator Node(AStar.PathFinderNode aStarNode) - { - return new Node - { - Position = new Point(aStarNode.X, aStarNode.Y), - F = aStarNode.F, - G = aStarNode.G - }; - } - } - - /// - /// Start position of the path. - /// - public Point Start { get; private set; } - - /// - /// A collision bytemap. - /// 0 = unwalkable node - /// 1 = walkable node - /// - public byte[,] CollisionMap; - - private Point goal; - /// - /// Sets a goal point and finds a path to it. - /// After a path is created, call Next() go get the next node in the path. - /// - public Point Goal - { - get { return goal; } - set - { - this.goal = value; - this.FindPath(this.Parent.GetComponent().Grid.Position, value, null); - } - } - - /// - /// Is a path in progress? - /// - public bool IsMoving - { - get - { - return path != null && path.Count() != 0; - } - } - - private AStar.PathFinderFast pathFinder; - private List path; - - public PathFinder(Entity parent) - : base(parent) - { - - } - - public override void Update(GameTime gameTime) - { - /*if (path != null && path.Count != 0) - { - var nextNode = path.Last(); - var nodePos = new Point(nextNode.X, nextNode.Y); - Parent.Transform.Grid.Position = nodePos; - if (Parent.Transform.World == (Vector2)Parent.Transform.Grid) - path.Remove(nextNode); - }*/ - - base.Update(gameTime); - } - - /// - /// Gets the next node of the current path. - /// - /// The next node in the path. - public Node Next() - { - if (path == null) - return null; - - if (path.Count == 0) - return null; - - var nextNode = path.Last(); - path.Remove(nextNode); - return (Node)nextNode; - } - - /// - /// Cancels the current path in memory. - /// - public void Stop() - { - path = null; - } - - /// - /// Finds a path between two points. - /// - /// The start point. - /// The goal point. - /// A list of unwalkable points that will be joined with the original collision map. - /// - private List FindPath(Point start, Point goal, List appendCollisionMap) - { - byte[,] mapCollisionMap = Core.Map.GetCollisionMap(); - - if (appendCollisionMap != null) - foreach (var point in appendCollisionMap) - mapCollisionMap[point.X, point.Y] = 0; - - pathFinder = new AStar.PathFinderFast(mapCollisionMap); - pathFinder.Formula = AStar.HeuristicFormula.Manhattan; - pathFinder.Diagonals = false; - pathFinder.HeavyDiagonals = false; - pathFinder.HeuristicEstimate = 2; - pathFinder.PunishChangeDirection = false; - pathFinder.TieBreaker = false; - pathFinder.SearchLimit = 50000; - pathFinder.DebugProgress = false; - pathFinder.DebugFoundPath = false; - - var _start = new System.Drawing.Point(start.X, start.Y); - var _goal = new System.Drawing.Point(goal.X, goal.Y); - //path = Core.PathFinder.FindPath(_start, _goal); - path = pathFinder.FindPath(_start, _goal); - if (path == null) - Debug.WriteLine(this.Parent.ToString() + ": Path not found!"); - - //this.CollisionMap = new byte[100, 100]; - - return path; - } - - /// - /// Recreate the current path in memory with a list of unwalkable points that will be joined with the original collision map. - /// - /// A list of unwalkable points that will be joined with the collision map. - public void RecreatePath(List appendCollisionMap) - { - FindPath(this.Parent.GetComponent().Grid.Position, this.Goal, appendCollisionMap); - } - } -} +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using AStar; +using Microsoft.Xna.Framework; + +namespace DepthsBelow.Component +{ + /// + /// Component that handles pathfinding. + /// + public class PathFinder : Component + { + /// + /// A pathfinder node. + /// + public class Node + { + /// + /// Grid position of the node. + /// + public Point Position; + /// + /// A* F-score + /// + public int F; + /// + /// A* G-score + /// + public int G; + + /// + /// Explicit conversion between A* library node and Node object. + /// + /// + /// + public static explicit operator Node(AStar.PathFinderNode aStarNode) + { + return new Node + { + Position = new Point(aStarNode.X, aStarNode.Y), + F = aStarNode.F, + G = aStarNode.G + }; + } + } + + /// + /// Start position of the path. + /// + public Point Start { get; private set; } + + /// + /// A collision bytemap. + /// 0 = unwalkable node + /// 1 = walkable node + /// + public byte[,] CollisionMap; + + private Point goal; + /// + /// Sets a goal point and finds a path to it. + /// After a path is created, call Next() go get the next node in the path. + /// + public Point Goal + { + get { return goal; } + set + { + this.goal = value; + this.FindPath(this.Parent.GetComponent().Grid.Position, value, null); + } + } + + /// + /// Is a path in progress? + /// + public bool IsMoving + { + get + { + return path != null && path.Count() != 0; + } + } + + public int Length + { + get + { + return (path != null) ? path.Count : 0; + } + } + + private AStar.PathFinderFast pathFinder; + private List path; + + public PathFinder(Entity parent) + : base(parent) + { + + } + + public override void Update(GameTime gameTime) + { + /*if (path != null && path.Count != 0) + { + var nextNode = path.Last(); + var nodePos = new Point(nextNode.X, nextNode.Y); + Parent.Transform.Grid.Position = nodePos; + if (Parent.Transform.World == (Vector2)Parent.Transform.Grid) + path.Remove(nextNode); + }*/ + + base.Update(gameTime); + } + + /// + /// Gets the next node of the current path. + /// + /// The next node in the path. + public Node Next() + { + if (path == null) + return null; + + if (path.Count == 0) + return null; + + var nextNode = path.Last(); + path.Remove(nextNode); + return (Node)nextNode; + } + + /// + /// Cancels the current path in memory. + /// + public void Stop() + { + path = null; + } + + /// + /// Finds a path between two points. + /// + /// The start point. + /// The goal point. + /// A list of unwalkable points that will be joined with the original collision map. + /// + private List FindPath(Point start, Point goal, List appendCollisionMap) + { + byte[,] mapCollisionMap = Core.Map.GetCollisionMap(); + + if (appendCollisionMap != null) + foreach (var point in appendCollisionMap) + mapCollisionMap[point.X, point.Y] = 0; + + pathFinder = new AStar.PathFinderFast(mapCollisionMap); + pathFinder.Formula = AStar.HeuristicFormula.Manhattan; + pathFinder.Diagonals = false; + pathFinder.HeavyDiagonals = false; + pathFinder.HeuristicEstimate = 2; + pathFinder.PunishChangeDirection = false; + pathFinder.TieBreaker = false; + pathFinder.SearchLimit = 50000; + pathFinder.DebugProgress = false; + pathFinder.DebugFoundPath = false; + + var _start = new System.Drawing.Point(start.X, start.Y); + var _goal = new System.Drawing.Point(goal.X, goal.Y); + //path = Core.PathFinder.FindPath(_start, _goal); + path = pathFinder.FindPath(_start, _goal); + if (path == null) + Debug.WriteLine(this.Parent.ToString() + ": Path not found!"); + + //this.CollisionMap = new byte[100, 100]; + + return path; + } + + /// + /// Recreate the current path in memory with a list of unwalkable points that will be joined with the original collision map. + /// + /// A list of unwalkable points that will be joined with the collision map. + public void RecreatePath(List appendCollisionMap) + { + FindPath(this.Parent.GetComponent().Grid.Position, this.Goal, appendCollisionMap); + } + } +} diff --git a/DepthsBelow/DepthsBelow/Interface.cs b/DepthsBelow/DepthsBelow/Interface.cs index df1b472..45a67fc 100755 --- a/DepthsBelow/DepthsBelow/Interface.cs +++ b/DepthsBelow/DepthsBelow/Interface.cs @@ -1,562 +1,581 @@ -using System; -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; -using Microsoft.Xna.Framework.Input; -using Microsoft.Xna.Framework.Content; - -namespace DepthsBelow -{ - public class Interface - { - Core core; - - /// - /// The master frame covering the whole game screen. Parent of all frames. - /// This frame handles all mouse interaction with the game world - /// - public Frame UIParent; - - public List PanicFrames = new List(); - public List UnitFrames = new List(); - public Dictionary SoldierToFrame = new Dictionary(); - - Random random = new Random(); - - private bool checkingDirection; - private Vector2 directionStart; - - public Interface(Core core) - { - this.core = core; - - UIParent = new Frame(); - UIParent.Width = GameServices.GetService().Viewport.Width; - UIParent.Height = GameServices.GetService().Viewport.Height; - - // Selection rectangle - var selectionFrame = new Frame(UIParent); - selectionFrame.Texture = Utility.GetSolidTexture(); - selectionFrame.Color = Color.Red * 0.5f; - selectionFrame.Visible = false; - UIParent["selectionFrame"] = selectionFrame; - - // OnPress - UIParent.OnPress += delegate(Frame frame, GUIManager.MouseEventArgs args) - { - //KeyboardState ks = Keyboard.GetState(); - MouseState ms = args.MouseState; - var mousePos = new Point(ms.X, ms.Y); - var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); - var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); - var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); - - // Show the selection frame - if (args.LeftButton == ButtonState.Pressed) - { - var selectFrame = (GUI.Frame)frame["selectionFrame"]; - if (!selectFrame.Visible) - { - selectFrame.X = mousePos.X; - selectFrame.Y = mousePos.Y; - selectFrame.Visible = true; - } - } - - if (args.RightButton == ButtonState.Pressed) - { - // Unit rotation - foreach (var unit in core.Squad) - { - if (unit.Selected && mouseWorldRectangle.Intersects(unit.GetComponent().Rectangle)) - { - checkingDirection = true; - directionStart = unit.Transform.World + unit.Transform.World.Origin; - } - } - } - }; - - // OnRelease - UIParent.OnRelease += delegate(Frame frame, GUIManager.MouseEventArgs args) - { - KeyboardState ks = Keyboard.GetState(); - MouseState ms = args.MouseState; - var mousePos = new Point(ms.X, ms.Y); - - var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); - var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); - var mouseGridPos= Grid.WorldToGrid(mouseWorldPos); - var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); - - if (args.LeftButton == ButtonState.Pressed) - { - // Deselect all units - if (!ks.IsKeyDown(Keys.LeftControl)) - { - foreach (var unit in core.Squad) - unit.Selected = false; - - foreach (var unitFrame in UnitFrames) - unitFrame.Color = Color.Black; - } - - // Select all soldier units inside the selection rectangle - var selectFrame = (GUI.Frame)frame["selectionFrame"]; - if (selectFrame.Visible) - { - Console.WriteLine("Before: " + selectFrame.AbsoluteRectangle.X + ", " + selectFrame.AbsoluteRectangle.Y + ", " + selectFrame.AbsoluteRectangle.Width + ", " + selectFrame.AbsoluteRectangle.Height); - - var intersectionRectangle = core.Camera.ScreenToWorld(selectFrame.AbsoluteRectangle); - - Console.WriteLine("After: " + intersectionRectangle.X + ", " + intersectionRectangle.Y + ", " + intersectionRectangle.Width + ", " + intersectionRectangle.Height); - - - // Select all units in the rectangle - foreach (var soldier in core.Squad) - { - if (intersectionRectangle.Intersects(soldier.GetComponent().Rectangle)) - { - soldier.Selected = true; - foreach (var unitFrame in UnitFrames) - { - if (unitFrame["soldier"] == soldier) - unitFrame.Color = Color.Blue; - } - } - } - - selectFrame.Visible = false; - } - } - - // Send orders with right click - if (args.RightButton == ButtonState.Pressed) - { - if (checkingDirection) - { - checkingDirection = false; - } - else - { - Debug.WriteLine("Right button pressed on UIParent"); - Point mainpath = Point.Zero; - Stack soldierStack = new Stack(); - //core.Squad.Where(a=>a.Selected).ToList().ForEach(a => soldierStack.Push(a)); - /*foreach (var soldier in core.Squad) - { - if (soldier.Selected) - { - soldierStack.Push(soldier); - } - }*/ - - // Don't move into other soldiers - bool blocked = false; - foreach (var soldier in core.Squad) - if (soldier.Position == mouseGridPos) - blocked = true; - - if (!blocked) - { - byte[,] collisionMap = Core.Map.GetCollisionMap(); - - // Try pathfinding - foreach (var unit in core.Squad) - { - if (unit.Selected) - { - if (mainpath == Point.Zero) - { - mainpath = unit.Position; - } - Vector2 fromMain = new Vector2((mainpath.X - unit.Position.X)*Grid.TileSize, - (mainpath.Y - unit.Position.Y)*Grid.TileSize); - var goal = Grid.WorldToGrid(mouseWorldPos - fromMain); - unit.GetComponent().Goal = goal; - if (unit.GetComponent().IsMoving == false) - { - // If a path was not found, add the unit to the stack - soldierStack.Push(unit); - } - else - { - collisionMap[goal.X, goal.Y] = 0; - } - } - } - - // Loop in a spiral and assign the soldiers in the stack their own unblocked positions - int X = 10; - int Y = 10; - int x, y, dx, dy; - x = y = dx = 0; - dy = -1; - int t = (int) MathHelper.Max(X, Y); - int maxI = t*t; - for (int i = 0; i < maxI; i++) - { - if ((-X/2 < x && x <= X/2) && (-Y/2 < y && y <= Y/2)) - { - Point point = new Point(x + mouseGridPos.X, y + mouseGridPos.Y); - if (collisionMap[point.X, point.Y] == 1) - { - if (soldierStack.Count == 0) - { - break; - } - var soldier = soldierStack.Pop(); - - if (soldier == null) - { - break; - } - else - { - soldier.GetComponent().Goal = point; - Console.WriteLine(x + " " + y); - Console.WriteLine(soldier.GetComponent().Goal.X + " " + - soldier.GetComponent().Goal.Y); - } - } - - - } - if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y))) - { - t = dx; - dx = -dy; - dy = t; - } - x += dx; - y += dy; - } - } - } - } - }; - - var button = new GUI.Button(UIParent); - button.SetTexture("images/Enter"); - button.X = 200; - button.Y = 100; - button.Width = 55; - button.Height = 40; - - // Test GUI frames - /*var frame = new GUI.Frame() - { - Y = 100 - }; - - var button = new GUI.Button(frame) - { - Width = 48, - Height = 23, - Texture = core.Content.Load("images/Enter"), - OnClick = delegate(Point clickPos) - { - Debug.WriteLine("That ugly button was clicked at (" + clickPos.X + "," + clickPos.Y + ")"); - } - }; - - 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.MouseEventArgs 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.MouseEventArgs 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.MouseEventArgs 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; - - 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.MouseEventArgs args) - { - if (frame.Color == Color.Blue) - frame.Color = Color.Yellow; - else - frame.Color = Color.Blue; - };*/ - } - - private GUI.Frame CreatePanicFrame() - { - var frame = new GUI.Frame(UIParent); - frame.SetTexture("images/GUI/unit_background"); - frame.Color = Color.Black; - frame.Width = 164; - frame.Height = 19; - - frame.OnClick += delegate(Frame frame1, GUIManager.MouseEventArgs args) - { - DynamicGroupManager.Group group = (DynamicGroupManager.Group)frame1["group"]; - if (group != null) - group.Panic += 5; - }; - - var panicBarBg = new GUI.Frame(frame); - panicBarBg.SetTexture("images/GUI/health_background"); - panicBarBg.Width = 136; - panicBarBg.Height = 13; - panicBarBg.X = 3; - panicBarBg.Y = 3; - frame["panicBarBg"] = panicBarBg; - - var panicBar = new GUI.Frame(panicBarBg); - panicBar.SetTexture("images/GUI/bar_solid"); - panicBar.Color = new Color(87, 55, 253); - panicBar.Width = (int)(panicBarBg.Width * 0.5); - panicBar.Height = 11; - panicBar.X = 1; - panicBar.Y = 1; - frame["panicBar"] = panicBar; - - var text = new GUI.Text(frame); - text.SetFont("fonts/UnitName"); - text.Value = "0%"; - text.X = 4; - text.Y = 1; - frame["text"] = text; - - return frame; - } - - private GUI.Frame CreateUnitFrame(Soldier soldier) - { - var frame = new GUI.Frame(UIParent); - 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 = soldier.Name + " "/* + soldier.GetHashCode()*/; - nameText.X = 4; - nameText.Y = 1; - frame["nameText"] = nameText; - - var healthBarBg = new GUI.Frame(frame); - healthBarBg.SetTexture("images/GUI/health_background"); - healthBarBg.Width = 136; - healthBarBg.Height = 13; - healthBarBg.X = 3; - healthBarBg.Y = 19; - frame["healthBarBg"] = healthBarBg; - - var healthBar = new GUI.Frame(healthBarBg); - healthBar.SetTexture("images/GUI/bar_solid"); - healthBar.Color = Color.Red; - healthBar.Width = (int)((healthBarBg.Width - 2) * (soldier.GetComponent().HP / soldier.GetComponent().MaxHP)); - healthBar.Height = 11; - healthBar.X = 1; - healthBar.Y = 1; - frame["healthBar"] = healthBar; - - return frame; - } - - public void CreateUnitFrames(List squad) - { - // TODO: ForEach squad in Squads... - /*GUI.Frame lastFrame = null; - foreach (Soldier soldier in squad) - { - // TODO: Remove this test ;) - soldier.GetComponent().HP = random.Next(0, (int) soldier.GetComponent().MaxHP - 1); - - var uFrame = CreateUnitFrame(soldier); - uFrame["soldier"] = soldier; - soldier["unitFrame"] = uFrame; - if (lastFrame != null) - { - uFrame.X = lastFrame.X; - uFrame.Y = lastFrame.Y + lastFrame.Height; - } - uFrame.OnClick += delegate(Frame f, GUIManager.MouseEventArgs e) - { - var s = (Soldier) f["soldier"]; - KeyboardState ks = Keyboard.GetState(); - - if (!ks.IsKeyDown(Keys.LeftControl)) - { - // Deselect all units - foreach (var unitFrame in UnitFrames) - { - ((Soldier) unitFrame["soldier"]).Selected = false; - unitFrame.Color = Color.Black; - } - } - - if (!s.Selected) - { - s.Selected = true; - uFrame.Color = Color.Blue; - } - }; - UnitFrames.Add(uFrame); - lastFrame = uFrame; - }*/ - - foreach (var soldier in squad) - { - PanicFrames.Add(CreatePanicFrame()); - - // TODO: Remove this test ;) - //soldier.GetComponent().HP = random.Next(0, (int)soldier.GetComponent().MaxHP - 1); - - var uFrame = CreateUnitFrame(soldier); - uFrame["soldier"] = soldier; - soldier["unitFrame"] = uFrame; - uFrame.OnPress += delegate(Frame frame, GUIManager.MouseEventArgs args) { }; - uFrame.OnRelease += delegate(Frame f, GUIManager.MouseEventArgs e) - { - var s = (Soldier)f["soldier"]; - KeyboardState ks = Keyboard.GetState(); - - if (!ks.IsKeyDown(Keys.LeftControl)) - { - // Deselect all units - foreach (var unitFrame in UnitFrames) - { - ((Soldier)unitFrame["soldier"]).Selected = false; - unitFrame.Color = Color.Black; - } - } - - if (!s.Selected) - { - s.Selected = true; - uFrame.Color = Color.Blue; - } - }; - UnitFrames.Add(uFrame); - } - } - - public void UpdateUnitFrames() - { - core.GroupManager.UpdateGroups(); - var groups = core.GroupManager.Groups; - - foreach (var panicFrame in PanicFrames) - panicFrame.Visible = false; - - GUI.Frame lastFrame = null; - for (int index = 0; index < groups.Count; index++) - { - var group = groups[index]; - - var pFrame = PanicFrames[index]; - pFrame["group"] = group; - var pFrameBarBg = (GUI.Frame)pFrame["panicBarBg"]; - var pFrameBar = (GUI.Frame)pFrame["panicBar"]; - var pFrameText = (GUI.Text)pFrame["text"]; - pFrameBar.Width = (int)(pFrameBarBg.Width * (group.Panic / group.MaxPanic)); - pFrameText.Value = group.Panic.ToString() + " (" + (group.Panic / group.MaxPanic * 100f).ToString() + "%)"; - - pFrame.Visible = true; - if (lastFrame != null) - { - pFrame.X = lastFrame.X; - pFrame.Y = lastFrame.Y + lastFrame.Height + 15; - } - lastFrame = pFrame; - - foreach (Soldier soldier in @group.Entities) - { - var frame = (GUI.Frame) soldier["unitFrame"]; - frame.X = lastFrame.X; - frame.Y = lastFrame.Y + lastFrame.Height; - - // Update HP - //var healthBarBg = (GUI.Frame)frame["healthBarBg"]; - //var healthBar = (GUI.Frame)frame["healthBar"]; - //healthBar.Width = (int)((healthBarBg.Width - 2) * (soldier.GetComponent().HP / soldier.GetComponent().MaxHP)); - - lastFrame = frame; - } - } - } - - public void Update(GameTime gameTime) - { - MouseState ms = Mouse.GetState(); - var mousePos = new Point(ms.X, ms.Y); - var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); - var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); - var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); - - // Update the selection rectangle - var selectionFrame = (GUI.Frame)UIParent["selectionFrame"]; - if (selectionFrame.Visible) - { - selectionFrame.Width = (int)mousePos.X - selectionFrame.X; - selectionFrame.Height = (int)mousePos.Y - selectionFrame.Y; - } - - // Update rotations - if (checkingDirection) - { - foreach (var unit in core.Squad) - if (unit.Selected) - { - float directionX = mouseWorldPos.X - unit.Transform.World.X; - float directionY = mouseWorldPos.Y - unit.Transform.World.Y; - //var mouseDirection = mouseWorldPos; - //mouseDirection.Normalize(); - unit.GetComponent().World.Rotation = - (float) - Math.Atan2(mouseWorldPos.Y - unit.Transform.World.Y - unit.Transform.World.Origin.Y, - mouseWorldPos.X - unit.Transform.World.X - unit.Transform.World.Origin.X); - } - } - - UpdateUnitFrames(); - } - } -} +using System; +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; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Content; + +namespace DepthsBelow +{ + public class Interface + { + Core core; + + /// + /// The master frame covering the whole game screen. Parent of all frames. + /// This frame handles all mouse interaction with the game world + /// + public Frame UIParent; + + public List PanicFrames = new List(); + public List UnitFrames = new List(); + public Dictionary SoldierToFrame = new Dictionary(); + + Random random = new Random(); + + private bool checkingDirection; + private Vector2 directionStart; + + public Interface(Core core) + { + this.core = core; + + UIParent = new Frame(); + UIParent.Width = GameServices.GetService().Viewport.Width; + UIParent.Height = GameServices.GetService().Viewport.Height; + + // Selection rectangle + var selectionFrame = new Frame(UIParent); + selectionFrame.Texture = Utility.GetSolidTexture(); + selectionFrame.Color = Color.Red * 0.5f; + selectionFrame.Visible = false; + UIParent["selectionFrame"] = selectionFrame; + + // OnPress + UIParent.OnPress += delegate(Frame frame, GUIManager.MouseEventArgs args) + { + //KeyboardState ks = Keyboard.GetState(); + MouseState ms = args.MouseState; + var mousePos = new Point(ms.X, ms.Y); + var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); + var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); + var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); + + // Show the selection frame + if (args.LeftButton == ButtonState.Pressed) + { + var selectFrame = (GUI.Frame)frame["selectionFrame"]; + if (!selectFrame.Visible) + { + selectFrame.X = mousePos.X; + selectFrame.Y = mousePos.Y; + selectFrame.Visible = true; + } + } + + if (args.RightButton == ButtonState.Pressed) + { + // Unit rotation + foreach (var unit in core.Squad) + { + if (unit.Selected && mouseWorldRectangle.Intersects(unit.GetComponent().Rectangle)) + { + checkingDirection = true; + directionStart = unit.Transform.World + unit.Transform.World.Origin; + } + } + } + }; + + // OnRelease + UIParent.OnRelease += delegate(Frame frame, GUIManager.MouseEventArgs args) + { + KeyboardState ks = Keyboard.GetState(); + MouseState ms = args.MouseState; + var mousePos = new Point(ms.X, ms.Y); + + var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); + var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); + var mouseGridPos= Grid.WorldToGrid(mouseWorldPos); + var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); + + if (args.LeftButton == ButtonState.Pressed) + { + // Deselect all units + if (!ks.IsKeyDown(Keys.LeftControl)) + { + foreach (var unit in core.Squad) + unit.Selected = false; + + foreach (var unitFrame in UnitFrames) + unitFrame.Color = Color.Black; + } + + // Select all soldier units inside the selection rectangle + var selectFrame = (GUI.Frame)frame["selectionFrame"]; + if (selectFrame.Visible) + { + Console.WriteLine("Before: " + selectFrame.AbsoluteRectangle.X + ", " + selectFrame.AbsoluteRectangle.Y + ", " + selectFrame.AbsoluteRectangle.Width + ", " + selectFrame.AbsoluteRectangle.Height); + + var intersectionRectangle = core.Camera.ScreenToWorld(selectFrame.AbsoluteRectangle); + + Console.WriteLine("After: " + intersectionRectangle.X + ", " + intersectionRectangle.Y + ", " + intersectionRectangle.Width + ", " + intersectionRectangle.Height); + + + // Select all units in the rectangle + foreach (var soldier in core.Squad) + { + if (intersectionRectangle.Intersects(soldier.GetComponent().Rectangle)) + { + soldier.Selected = true; + foreach (var unitFrame in UnitFrames) + { + if (unitFrame["soldier"] == soldier) + unitFrame.Color = Color.Blue; + } + } + } + + selectFrame.Visible = false; + } + } + + // Send orders with right click + if (args.RightButton == ButtonState.Pressed) + { + if (checkingDirection) + { + checkingDirection = false; + } + else + { + Debug.WriteLine("Right button pressed on UIParent"); + Point mainpath = Point.Zero; + Stack soldierStack = new Stack(); + //core.Squad.Where(a=>a.Selected).ToList().ForEach(a => soldierStack.Push(a)); + /*foreach (var soldier in core.Squad) + { + if (soldier.Selected) + { + soldierStack.Push(soldier); + } + }*/ + + // Don't move into other soldiers + bool blocked = false; + foreach (var soldier in core.Squad) + if (soldier.Position == mouseGridPos) + blocked = true; + + if (!blocked) + { + byte[,] collisionMap = Core.Map.GetCollisionMap(); + + // Try pathfinding + foreach (var unit in core.Squad) + { + if (unit.Selected) + { + if (mainpath == Point.Zero) + { + mainpath = unit.Position; + } + Vector2 fromMain = new Vector2((mainpath.X - unit.Position.X)*Grid.TileSize, + (mainpath.Y - unit.Position.Y)*Grid.TileSize); + var goal = Grid.WorldToGrid(mouseWorldPos - fromMain); + Console.WriteLine("First " + unit.AP); + unit.GetComponent().Goal = goal; + var length = unit.GetComponent().Length - 1; + if (unit.AP >= length) + { + + if (unit.GetComponent().IsMoving == false) + { + // If a path was not found, add the unit to the stack + soldierStack.Push(unit); + } + else + { + unit.AP -= length; + Console.WriteLine("then " + unit.AP); + collisionMap[goal.X, goal.Y] = 0; + } + } + else + { + unit.GetComponent().Stop(); + } + + } + } + + // Loop in a spiral and assign the soldiers in the stack their own unblocked positions + int X = 10; + int Y = 10; + int x, y, dx, dy; + x = y = dx = 0; + dy = -1; + int t = (int) MathHelper.Max(X, Y); + int maxI = t*t; + for (int i = 0; i < maxI; i++) + { + if ((-X/2 < x && x <= X/2) && (-Y/2 < y && y <= Y/2)) + { + Point point = new Point(x + mouseGridPos.X, y + mouseGridPos.Y); + if (collisionMap[point.X, point.Y] == 1) + { + if (soldierStack.Count == 0) + { + break; + } + var soldier = soldierStack.Pop(); + + if (soldier == null) + { + break; + } + else + { + if (soldier.AP >= soldier.GetComponent().Length) + { + soldier.GetComponent().Goal = point; + soldier.AP -= soldier.GetComponent().Length; + + Console.WriteLine(x + " " + y); + Console.WriteLine(soldier.GetComponent().Goal.X + " " + + soldier.GetComponent().Goal.Y); + + } + } + } + + + } + if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y))) + { + t = dx; + dx = -dy; + dy = t; + } + x += dx; + y += dy; + } + } + } + } + }; + + var button = new GUI.Button(UIParent); + button.SetTexture("images/Enter"); + button.X = 200; + button.Y = 100; + button.Width = 55; + button.Height = 40; + + // Test GUI frames + /*var frame = new GUI.Frame() + { + Y = 100 + }; + + var button = new GUI.Button(frame) + { + Width = 48, + Height = 23, + Texture = core.Content.Load("images/Enter"), + OnClick = delegate(Point clickPos) + { + Debug.WriteLine("That ugly button was clicked at (" + clickPos.X + "," + clickPos.Y + ")"); + } + }; + + 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.MouseEventArgs 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.MouseEventArgs 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.MouseEventArgs 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; + + 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.MouseEventArgs args) + { + if (frame.Color == Color.Blue) + frame.Color = Color.Yellow; + else + frame.Color = Color.Blue; + };*/ + } + + private GUI.Frame CreatePanicFrame() + { + var frame = new GUI.Frame(UIParent); + frame.SetTexture("images/GUI/unit_background"); + frame.Color = Color.Black; + frame.Width = 164; + frame.Height = 19; + + frame.OnClick += delegate(Frame frame1, GUIManager.MouseEventArgs args) + { + DynamicGroupManager.Group group = (DynamicGroupManager.Group)frame1["group"]; + if (group != null) + group.Panic += 5; + }; + + var panicBarBg = new GUI.Frame(frame); + panicBarBg.SetTexture("images/GUI/health_background"); + panicBarBg.Width = 136; + panicBarBg.Height = 13; + panicBarBg.X = 3; + panicBarBg.Y = 3; + frame["panicBarBg"] = panicBarBg; + + var panicBar = new GUI.Frame(panicBarBg); + panicBar.SetTexture("images/GUI/bar_solid"); + panicBar.Color = new Color(87, 55, 253); + panicBar.Width = (int)(panicBarBg.Width * 0.5); + panicBar.Height = 11; + panicBar.X = 1; + panicBar.Y = 1; + frame["panicBar"] = panicBar; + + var text = new GUI.Text(frame); + text.SetFont("fonts/UnitName"); + text.Value = "0%"; + text.X = 4; + text.Y = 1; + frame["text"] = text; + + return frame; + } + + private GUI.Frame CreateUnitFrame(Soldier soldier) + { + var frame = new GUI.Frame(UIParent); + 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 = soldier.Name + " "/* + soldier.GetHashCode()*/; + nameText.X = 4; + nameText.Y = 1; + frame["nameText"] = nameText; + + var healthBarBg = new GUI.Frame(frame); + healthBarBg.SetTexture("images/GUI/health_background"); + healthBarBg.Width = 136; + healthBarBg.Height = 13; + healthBarBg.X = 3; + healthBarBg.Y = 19; + frame["healthBarBg"] = healthBarBg; + + var healthBar = new GUI.Frame(healthBarBg); + healthBar.SetTexture("images/GUI/bar_solid"); + healthBar.Color = Color.Red; + healthBar.Width = (int)((healthBarBg.Width - 2) * (soldier.GetComponent().HP / soldier.GetComponent().MaxHP)); + healthBar.Height = 11; + healthBar.X = 1; + healthBar.Y = 1; + frame["healthBar"] = healthBar; + + return frame; + } + + public void CreateUnitFrames(List squad) + { + // TODO: ForEach squad in Squads... + /*GUI.Frame lastFrame = null; + foreach (Soldier soldier in squad) + { + // TODO: Remove this test ;) + soldier.GetComponent().HP = random.Next(0, (int) soldier.GetComponent().MaxHP - 1); + + var uFrame = CreateUnitFrame(soldier); + uFrame["soldier"] = soldier; + soldier["unitFrame"] = uFrame; + if (lastFrame != null) + { + uFrame.X = lastFrame.X; + uFrame.Y = lastFrame.Y + lastFrame.Height; + } + uFrame.OnClick += delegate(Frame f, GUIManager.MouseEventArgs e) + { + var s = (Soldier) f["soldier"]; + KeyboardState ks = Keyboard.GetState(); + + if (!ks.IsKeyDown(Keys.LeftControl)) + { + // Deselect all units + foreach (var unitFrame in UnitFrames) + { + ((Soldier) unitFrame["soldier"]).Selected = false; + unitFrame.Color = Color.Black; + } + } + + if (!s.Selected) + { + s.Selected = true; + uFrame.Color = Color.Blue; + } + }; + UnitFrames.Add(uFrame); + lastFrame = uFrame; + }*/ + + foreach (var soldier in squad) + { + PanicFrames.Add(CreatePanicFrame()); + + // TODO: Remove this test ;) + //soldier.GetComponent().HP = random.Next(0, (int)soldier.GetComponent().MaxHP - 1); + + var uFrame = CreateUnitFrame(soldier); + uFrame["soldier"] = soldier; + soldier["unitFrame"] = uFrame; + uFrame.OnPress += delegate(Frame frame, GUIManager.MouseEventArgs args) { }; + uFrame.OnRelease += delegate(Frame f, GUIManager.MouseEventArgs e) + { + var s = (Soldier)f["soldier"]; + KeyboardState ks = Keyboard.GetState(); + + if (!ks.IsKeyDown(Keys.LeftControl)) + { + // Deselect all units + foreach (var unitFrame in UnitFrames) + { + ((Soldier)unitFrame["soldier"]).Selected = false; + unitFrame.Color = Color.Black; + } + } + + if (!s.Selected) + { + s.Selected = true; + uFrame.Color = Color.Blue; + } + }; + UnitFrames.Add(uFrame); + } + } + + public void UpdateUnitFrames() + { + core.GroupManager.UpdateGroups(); + var groups = core.GroupManager.Groups; + + foreach (var panicFrame in PanicFrames) + panicFrame.Visible = false; + + GUI.Frame lastFrame = null; + for (int index = 0; index < groups.Count; index++) + { + var group = groups[index]; + + var pFrame = PanicFrames[index]; + pFrame["group"] = group; + var pFrameBarBg = (GUI.Frame)pFrame["panicBarBg"]; + var pFrameBar = (GUI.Frame)pFrame["panicBar"]; + var pFrameText = (GUI.Text)pFrame["text"]; + pFrameBar.Width = (int)(pFrameBarBg.Width * (group.Panic / group.MaxPanic)); + pFrameText.Value = group.Panic.ToString() + " (" + (group.Panic / group.MaxPanic * 100f).ToString() + "%)"; + + pFrame.Visible = true; + if (lastFrame != null) + { + pFrame.X = lastFrame.X; + pFrame.Y = lastFrame.Y + lastFrame.Height + 15; + } + lastFrame = pFrame; + + foreach (Soldier soldier in @group.Entities) + { + var frame = (GUI.Frame) soldier["unitFrame"]; + frame.X = lastFrame.X; + frame.Y = lastFrame.Y + lastFrame.Height; + + // Update HP + //var healthBarBg = (GUI.Frame)frame["healthBarBg"]; + //var healthBar = (GUI.Frame)frame["healthBar"]; + //healthBar.Width = (int)((healthBarBg.Width - 2) * (soldier.GetComponent().HP / soldier.GetComponent().MaxHP)); + + lastFrame = frame; + } + } + } + + public void Update(GameTime gameTime) + { + MouseState ms = Mouse.GetState(); + var mousePos = new Point(ms.X, ms.Y); + var mouseRectangle = new Rectangle(mousePos.X, mousePos.Y, 1, 1); + var mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(mousePos.X, mousePos.Y)); + var mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1); + + // Update the selection rectangle + var selectionFrame = (GUI.Frame)UIParent["selectionFrame"]; + if (selectionFrame.Visible) + { + selectionFrame.Width = (int)mousePos.X - selectionFrame.X; + selectionFrame.Height = (int)mousePos.Y - selectionFrame.Y; + } + + // Update rotations + if (checkingDirection) + { + foreach (var unit in core.Squad) + if (unit.Selected) + { + float directionX = mouseWorldPos.X - unit.Transform.World.X; + float directionY = mouseWorldPos.Y - unit.Transform.World.Y; + //var mouseDirection = mouseWorldPos; + //mouseDirection.Normalize(); + unit.GetComponent().World.Rotation = + (float) + Math.Atan2(mouseWorldPos.Y - unit.Transform.World.Y - unit.Transform.World.Origin.Y, + mouseWorldPos.X - unit.Transform.World.X - unit.Transform.World.Origin.X); + } + } + + UpdateUnitFrames(); + } + } +} diff --git a/DepthsBelow/DepthsBelow/KeyboardInput.cs b/DepthsBelow/DepthsBelow/KeyboardInput.cs index ab14ccc..0d740d3 100755 --- a/DepthsBelow/DepthsBelow/KeyboardInput.cs +++ b/DepthsBelow/DepthsBelow/KeyboardInput.cs @@ -140,7 +140,7 @@ namespace DepthsBelow { foreach (var unit in core.Squad) { - unit.AP = 0; + unit.AP = unit.MaxActionPoints; unit.Fired = false; } @@ -227,10 +227,10 @@ namespace DepthsBelow cost = rocketCost; type = "Rocket"; } - if (soldier.AP <= soldier.NumberOfActionPoints - cost) + if (soldier.AP >= cost) { core.Volley.Add(new Shot(core.EntityManager, soldier.GetComponent(), type)); - soldier.AP += cost; + soldier.AP -= cost; soldier.Fired = true; } else diff --git a/DepthsBelow/DepthsBelow/Soldier.cs b/DepthsBelow/DepthsBelow/Soldier.cs index ac5a2a3..38f1b32 100755 --- a/DepthsBelow/DepthsBelow/Soldier.cs +++ b/DepthsBelow/DepthsBelow/Soldier.cs @@ -35,16 +35,16 @@ namespace DepthsBelow } } - public int NumberOfActionPoints = 10; - int spentActionPoints = 0; + public int MaxActionPoints = 10; + int actionPointsLeft = 0; public int AP { - get { return spentActionPoints; } + get { return actionPointsLeft; } set { - spentActionPoints = value; - GetComponent().GetStep = spentActionPoints; + actionPointsLeft = value; + GetComponent().GetStep = actionPointsLeft; } } @@ -174,17 +174,17 @@ namespace DepthsBelow if (Transform.World == nodeWorldPos) { - if (AP < NumberOfActionPoints) - { - AP++; + //if (AP < NumberOfActionPoints) + //{ + //AP++; lastLastNode = lastNode; lastNode = nextNode; nextNode = GetComponent().Next(); - } - else + //} + /*else { GetComponent().Stop(); - } + }*/ } } }