diff --git a/DepthsBelow/DepthsBelow/Component/Collision.cs b/DepthsBelow/DepthsBelow/Component/Collision.cs index 53b0149..c61f7fa 100644 --- a/DepthsBelow/DepthsBelow/Component/Collision.cs +++ b/DepthsBelow/DepthsBelow/Component/Collision.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; namespace DepthsBelow.Component { @@ -21,11 +23,12 @@ namespace DepthsBelow.Component this.Height = height; this.Rectangle = new Rectangle(0, 0, width, height); } + public override void Update(GameTime gameTime) { - PixelTransform pt = this.Parent.GetComponent(); - this.Rectangle.X = (int)pt.X; - this.Rectangle.Y = (int)pt.Y; + Transform transform = this.Parent.GetComponent(); + this.Rectangle.X = (int)transform.World.X; + this.Rectangle.Y = (int)transform.World.Y; } } } diff --git a/DepthsBelow/DepthsBelow/Component/GridTransform.cs b/DepthsBelow/DepthsBelow/Component/GridTransform.cs index aa8b7ab..823aeba 100644 --- a/DepthsBelow/DepthsBelow/Component/GridTransform.cs +++ b/DepthsBelow/DepthsBelow/Component/GridTransform.cs @@ -6,6 +6,7 @@ using Microsoft.Xna.Framework; namespace DepthsBelow.Component { + [Obsolete("Deprecated in favour of Component.Transform")] public class GridTransform : Component { public Point Position; diff --git a/DepthsBelow/DepthsBelow/Component/PathFinder.cs b/DepthsBelow/DepthsBelow/Component/PathFinder.cs index 072d55b..4dad9d7 100755 --- a/DepthsBelow/DepthsBelow/Component/PathFinder.cs +++ b/DepthsBelow/DepthsBelow/Component/PathFinder.cs @@ -3,25 +3,47 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; +using AStar; using Microsoft.Xna.Framework; namespace DepthsBelow.Component { - class PathFinder : Component + public class PathFinder : Component { + public class Node + { + public Point Position; + public int F; + public int G; + + public static explicit operator Node(AStar.PathFinderNode aStarNode) + { + return new Node + { + Position = new Point(aStarNode.X, aStarNode.Y), + F = aStarNode.F, + G = aStarNode.G + }; + } + } + public Point Start { get; private set; } + + public byte[,] CollisionMap; + + private Point goal; public Point Goal { get { return goal; } set { this.goal = value; - this.Start = this.Parent.GetComponent().Position; - this.FindPath(this.Start, value); + //this.Start = this.Parent.GetComponent().Grid.Position; + this.FindPath(this.Parent.GetComponent().Grid.Position, value, null); } } - - private Point goal; + + private AStar.PathFinderFast pathFinder; private List path; public PathFinder(Entity parent) @@ -32,26 +54,45 @@ namespace DepthsBelow.Component public override void Update(GameTime gameTime) { - if (path != null && path.Count != 0) + /*if (path != null && path.Count != 0) { var nextNode = path.Last(); var nodePos = new Point(nextNode.X, nextNode.Y); - Parent.gridTransform.Position = nodePos; - if (Parent.pixelTransform.Position == Parent.gridTransform.ToWorld()) + Parent.Transform.Grid.Position = nodePos; + if (Parent.Transform.World == (Vector2)Parent.Transform.Grid) path.Remove(nextNode); - } + }*/ base.Update(gameTime); } - public void FindPath(Point start, Point goal) + public Node Next() { - AStar.PathFinderFast pathFinder = new AStar.PathFinderFast(Core.Map.GetCollisionMap()); + if (path == null) + return null; + + if (path.Count == 0) + return null; + + var nextNode = path.Last(); + path.Remove(nextNode); + return (Node)nextNode; + } + + 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 = true; + pathFinder.PunishChangeDirection = false; pathFinder.TieBreaker = false; pathFinder.SearchLimit = 50000; pathFinder.DebugProgress = false; @@ -63,6 +104,15 @@ namespace DepthsBelow.Component path = pathFinder.FindPath(_start, _goal); if (path == null) Debug.WriteLine(this.Parent.ToString() + ": Path not found!"); + + this.CollisionMap = new byte[100, 100]; + + return path; + } + + public void RecreatePath(List appendCollisionMap) + { + FindPath(this.Parent.GetComponent().Grid.Position, this.Goal, appendCollisionMap); } } } diff --git a/DepthsBelow/DepthsBelow/Component/PixelTransform.cs b/DepthsBelow/DepthsBelow/Component/PixelTransform.cs index e9332d3..865b6f0 100644 --- a/DepthsBelow/DepthsBelow/Component/PixelTransform.cs +++ b/DepthsBelow/DepthsBelow/Component/PixelTransform.cs @@ -6,6 +6,7 @@ using Microsoft.Xna.Framework; namespace DepthsBelow.Component { + [Obsolete("Deprecated in favour of Component.Transform")] public class PixelTransform : Component { public Vector2 Position; diff --git a/DepthsBelow/DepthsBelow/Component/SpriteRenderer.cs b/DepthsBelow/DepthsBelow/Component/SpriteRenderer.cs index ab0972b..e7a2093 100644 --- a/DepthsBelow/DepthsBelow/Component/SpriteRenderer.cs +++ b/DepthsBelow/DepthsBelow/Component/SpriteRenderer.cs @@ -23,9 +23,9 @@ namespace DepthsBelow.Component public void Draw(SpriteBatch spriteBatch) { - PixelTransform transform = this.Parent.GetComponent(); + Transform transform = this.Parent.GetComponent(); //spriteBatch.Draw(Texture, tc.Position, this.Color); - spriteBatch.Draw(Texture, transform.Position + transform.Origin, null, Color, transform.Rotation, transform.Origin, Scale, SpriteEffects, 0); + spriteBatch.Draw(Texture, transform.World.Position + transform.World.Origin, null, Color, transform.World.Rotation, transform.World.Origin, Scale, SpriteEffects, 0); } } } diff --git a/DepthsBelow/DepthsBelow/Component/Transform.cs b/DepthsBelow/DepthsBelow/Component/Transform.cs new file mode 100755 index 0000000..c7a451c --- /dev/null +++ b/DepthsBelow/DepthsBelow/Component/Transform.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework; + +namespace DepthsBelow.Component +{ + public class Transform : Component + { + public class GridTransform + { + private Point position; + public Point Position + { + get { return position; } + set + { + position = value; + masterTransform.World.SetWithoutRelation((Vector2)this); + } + } + + public int X + { + get { return position.X; } + set + { + position.X = value; + masterTransform.World.SetWithoutRelation((Vector2)this); + } + } + public int Y + { + get { return position.Y; } + set + { + position.Y = value; + masterTransform.World.SetWithoutRelation((Vector2)this); + } + } + + public static implicit operator Point(GridTransform gridTransform) + { + return gridTransform.position; + } + + public static explicit operator Vector2(GridTransform gridTransform) + { + var worldPosition = DepthsBelow.Grid.GridToWorld(gridTransform.Position); + return new Vector2(worldPosition.X, worldPosition.Y); + } + + private readonly Transform masterTransform; + public GridTransform(Transform masterTransform) + { + this.masterTransform = masterTransform; + } + + public void SetWithoutRelation(Point position) + { + this.position = position; + } + } + + public class WorldTransform + { + private Vector2 position; + public Vector2 Position + { + get { return position; } + set + { + position = value; + masterTransform.Grid.SetWithoutRelation((Point)this); + } + } + + public float X + { + get { return position.X; } + set + { + position.X = value; + masterTransform.Grid.SetWithoutRelation((Point)this); + } + } + public float Y + { + get { return position.Y; } + set + { + position.Y = value; + masterTransform.Grid.SetWithoutRelation((Point)this); + } + } + + public float Rotation; + + public void Rotate(int directionX, int directionY) + { + Rotation = (float)Math.Atan(directionY/directionX); + } + + public Vector2 Origin; + + public static implicit operator Vector2(WorldTransform worldTransform) + { + return worldTransform.Position; + } + + public static explicit operator Point(WorldTransform worldTransform) + { + var gridPosition = DepthsBelow.Grid.WorldToGrid(worldTransform.Position); + return new Point(gridPosition.X, gridPosition.Y); + } + + private readonly Transform masterTransform; + public WorldTransform(Transform masterTransform) + { + this.masterTransform = masterTransform; + } + + public void SetWithoutRelation(Vector2 position) + { + this.position = position; + } + } + + public GridTransform Grid; + public WorldTransform World; + + public Transform(Entity parent) + : base(parent) + { + Grid = new GridTransform(this); + World = new WorldTransform(this); + } + + public static implicit operator Point(Transform transform) + { + return transform.Grid; + } + + public static implicit operator Vector2(Transform transform) + { + return transform.World; + } + } +} diff --git a/DepthsBelow/DepthsBelow/DepthsBelow.csproj b/DepthsBelow/DepthsBelow/DepthsBelow.csproj index 121db3f..9cf179b 100644 --- a/DepthsBelow/DepthsBelow/DepthsBelow.csproj +++ b/DepthsBelow/DepthsBelow/DepthsBelow.csproj @@ -123,6 +123,7 @@ + diff --git a/DepthsBelow/DepthsBelow/Entity.cs b/DepthsBelow/DepthsBelow/Entity.cs index b35f26e..838dc97 100644 --- a/DepthsBelow/DepthsBelow/Entity.cs +++ b/DepthsBelow/DepthsBelow/Entity.cs @@ -9,34 +9,35 @@ namespace DepthsBelow public class Entity { List Components; + public Component.Transform Transform; public Component.PixelTransform pixelTransform; public Component.GridTransform gridTransform; public int X { - get { return this.gridTransform.X; } + get { return this.Transform.Grid.X; } set - { - this.gridTransform.X = value; - this.pixelTransform.X = this.gridTransform.ToWorld().X; + { + this.Transform.Grid.X = value; } } public int Y { - get { return this.gridTransform.Y; } + get { return this.Transform.Grid.Y; } set { - this.gridTransform.Y = value; - this.pixelTransform.Y = this.gridTransform.ToWorld().Y; + this.Transform.Grid.Y = value; } } - private Core core; + protected Core core; public Entity(Core core) { this.core = core; Components = new List(); + Transform = new Component.Transform(this); + AddComponent(Transform); pixelTransform = new Component.PixelTransform(this); AddComponent(pixelTransform); gridTransform = new Component.GridTransform(this); diff --git a/DepthsBelow/DepthsBelow/Map.cs b/DepthsBelow/DepthsBelow/Map.cs index f31cabf..00dc2f0 100755 --- a/DepthsBelow/DepthsBelow/Map.cs +++ b/DepthsBelow/DepthsBelow/Map.cs @@ -86,7 +86,7 @@ namespace DepthsBelow { if (mapObject.Type == "SquadStart") { - var soldier = new Soldier(core); + var soldier = new Soldier(core, ref core.Squad); // HACK: For some reason, the tile object coordinates are offset by one tile on the Y-axis in the Tiled map file (https://github.com/bjorn/tiled/issues/91) var mapObjectPos = new Vector2(mapObject.Bounds.X, mapObject.Bounds.Y - Grid.TileSize); var mapObjectGridPos = Grid.WorldToGrid(mapObjectPos); diff --git a/DepthsBelow/DepthsBelow/MouseInput.cs b/DepthsBelow/DepthsBelow/MouseInput.cs index 10d9427..b8d911a 100755 --- a/DepthsBelow/DepthsBelow/MouseInput.cs +++ b/DepthsBelow/DepthsBelow/MouseInput.cs @@ -19,6 +19,12 @@ namespace DepthsBelow Rectangle gridRectangle; Texture2D gridTexture; + Vector2 directionStart; + Vector2 directionNow; + + bool checkingDirection = false; + + public MouseInput(Core core) { this.core = core; @@ -27,6 +33,7 @@ namespace DepthsBelow gridRectangle = Rectangle.Empty; } + public void LoadContent() { selectionTexture = new Texture2D(core.GraphicsDevice, 1, 1); @@ -84,9 +91,52 @@ namespace DepthsBelow if (ms.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed) { foreach (var unit in core.Squad) - if (unit.Selected) + if (unit.Selected) + { unit.GetComponent().Goal = Grid.WorldToGrid(mouseWorldPos); + } + } + if (ms.RightButton == ButtonState.Pressed) + { + foreach (var unit in core.Squad) + { + if (unit.Selected && gridRectangle.Intersects(unit.GetComponent().Rectangle)) + { + checkingDirection = true; + directionStart = unit.Transform.World + unit.Transform.World.Origin; + } + } + } + if (checkingDirection == true && ms.RightButton == ButtonState.Pressed) + { + foreach (var unit in core.Squad) + if (unit.Selected) + { + directionNow.X = mouseWorldPos.X; + directionNow.Y = mouseWorldPos.Y; + float directionX = mouseWorldPos.X - unit.Transform.World.X; + float directionY = mouseWorldPos.Y - unit.Transform.World.Y; + var mouseDirection = mouseWorldPos; + mouseDirection.Normalize(); + //float angle = (float)Math.Acos(Vector2.Dot(new Vector2(0, 1), mouseDirection)) * MathHelper.TwoPi; + /*if (directionX < 0) + { + directionX *= -1; + unit.GetComponent().World.Rotation = (float)Math.Atan(directionY / directionX); + } + else + { + */unit.GetComponent().World.Rotation = (float)Math.Atan2(mouseWorldPos.Y - unit.Transform.World.Y, mouseWorldPos.X - unit.Transform.World.X);/* + }*/ + //Console.WriteLine(angle); + //unit.GetComponent().World.Rotation = angle; + } + } + else + { + checkingDirection = false; + } // Grid highlighting Point mouseGridPos = Grid.WorldToGrid(mouseWorldPos); @@ -100,6 +150,24 @@ namespace DepthsBelow { spriteBatch.Draw(selectionTexture, selectionRectangle, Color.Red * 0.5f); spriteBatch.Draw(gridTexture, gridRectangle, Color.Yellow * 0.3f); + + if (checkingDirection == true) + { + Texture2D blank = new Texture2D(core.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); + blank.SetData(new[] { Color.White }); + DrawLine(spriteBatch, blank, 2, Color.White, directionStart, directionNow); + } + } + + void DrawLine(SpriteBatch batch, Texture2D blank, float width, Color color, Vector2 point1, Vector2 point2) + { + float angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); + float length = Vector2.Distance(point1, point2); + + batch.Draw(blank, point1, null, color, + angle, Vector2.Zero, new Vector2(length, width), + SpriteEffects.None, 0); + } } } diff --git a/DepthsBelow/DepthsBelow/Soldier.cs b/DepthsBelow/DepthsBelow/Soldier.cs index bda0099..336e7c6 100644 --- a/DepthsBelow/DepthsBelow/Soldier.cs +++ b/DepthsBelow/DepthsBelow/Soldier.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using DepthsBelow.Component; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -13,16 +14,18 @@ namespace DepthsBelow public static Point Origin; private bool _selected; - private KeyboardState lastKeyboardState; + public List Squad; - public Soldier(Core core) : base(core) + private PathFinder.Node nextNode; + + public Soldier(Core core, ref List squad) : base(core) { if (Texture == null) LoadContent(core); - pixelTransform.Origin = new Vector2(16, 16); - //gridTransform.Position = new Point(7, 3); - //pixelTransform.Position = gridTransform.ToWorld(); + this.Squad = squad; + + Transform.World.Origin = new Vector2(16, 16); this.Color = Color.White; var rc = new SpriteRenderer(this) {Texture = Texture, Color = Color.White}; @@ -53,39 +56,53 @@ namespace DepthsBelow public override void Update(GameTime gameTime) { base.Update(gameTime); - KeyboardState ks = Keyboard.GetState(); - if (ks.IsKeyDown(Keys.Right) && lastKeyboardState.IsKeyUp(Keys.Right)) + + float elapsed = gameTime.ElapsedGameTime.Milliseconds / 1000.0f; + + if (nextNode == null) + nextNode = GetComponent().Next(); + + if (nextNode != null) { - gridTransform.X += 1; - pixelTransform.Rotation = (float)0; + List soldierCollisions = new List(); + + foreach (var soldier in Squad) + { + if (soldier != this) + { + if (soldier.Transform.Grid == nextNode.Position) + { + soldierCollisions.Add(soldier.Transform.Grid); + GetComponent().RecreatePath(soldierCollisions); + nextNode = GetComponent().Next(); + break; + } + } + } + + + + if (nextNode != null) + { + var nodeWorldPos = Grid.GridToWorld(nextNode.Position); + // HACK: Make this work properly with other speeds... + float speed = 4f; + if (Transform.World.X < nodeWorldPos.X) + Transform.World.X += speed; + if (Transform.World.X > nodeWorldPos.X) + Transform.World.X -= speed; + if (Transform.World.Y < nodeWorldPos.Y) + Transform.World.Y += speed; + if (Transform.World.Y > nodeWorldPos.Y) + Transform.World.Y -= speed; + + if (Transform.World == nodeWorldPos) + nextNode = GetComponent().Next(); + } + } - if (ks.IsKeyDown(Keys.Left) && lastKeyboardState.IsKeyUp(Keys.Left)) - { - gridTransform.X -= 1; - pixelTransform.Rotation = (float)Math.PI; - } - if (ks.IsKeyDown(Keys.Up) && lastKeyboardState.IsKeyUp(Keys.Up)) - { - gridTransform.Y -= 1; - pixelTransform.Rotation = (float)(3.0f*Math.PI/2.0f); - } - if (ks.IsKeyDown(Keys.Down) && lastKeyboardState.IsKeyUp(Keys.Down)) - { - gridTransform.Y += 1; - pixelTransform.Rotation = (float)(Math.PI / 2.0f); - } - lastKeyboardState = ks; - - int speed = 1; - if (pixelTransform.X < gridTransform.ToWorld().X) - pixelTransform.X += speed; - if (pixelTransform.X > gridTransform.ToWorld().X) - pixelTransform.X -= speed; - if (pixelTransform.Y < gridTransform.ToWorld().Y) - pixelTransform.Y += speed; - if (pixelTransform.Y > gridTransform.ToWorld().Y) - pixelTransform.Y -= speed; + /**/ } } } \ No newline at end of file