Working unit frames and dynamic soldier grouping

This commit is contained in:
Simon Holmberg
2012-10-21 22:50:18 +02:00
parent f8c1422eeb
commit cf3bc09a4a
16 changed files with 885 additions and 146 deletions
+21
View File
@@ -35,11 +35,27 @@ namespace DepthsBelow
return Vector2.Transform(screenPos, Matrix.Invert(Transform));
}
public Rectangle ScreenToWorld(Rectangle screenRectangle)
{
var pos = ScreenToWorld(new Vector2(screenRectangle.X, screenRectangle.Y));
screenRectangle.X = (int)pos.X;
screenRectangle.Y = (int)pos.Y;
return screenRectangle;
}
public Vector2 WorldToScreen(Vector2 worldPos)
{
return Vector2.Transform(worldPos, Transform);
}
public Rectangle WorldToScreen(Rectangle screenRectangle)
{
var pos = WorldToScreen(new Vector2(screenRectangle.X, screenRectangle.Y));
screenRectangle.X = (int)pos.X;
screenRectangle.Y = (int)pos.Y;
return screenRectangle;
}
public void Update(GameTime gameTime)
{
float elapsed = gameTime.ElapsedGameTime.Milliseconds / 1000.0f;
@@ -85,6 +101,11 @@ namespace DepthsBelow
Transform *= Matrix.CreateTranslation(new Vector3(change.X, change.Y, 0));
}
Transform = Matrix.Identity
* Matrix.CreateRotationZ(Rotation)
* Matrix.CreateScale(Zoom)
* Matrix.CreateTranslation(new Vector3(Position.X, Position.Y, 0));
lastMouseState = ms;
}
}
+24 -4
View File
@@ -5,9 +5,28 @@ using System.Text;
namespace DepthsBelow.Component
{
public class Stat : Component
{
protected int hp = 0;
public class Stat : Component
{
/// <summary>
/// The current health points of the unit
/// </summary>
public float HP = 0;
public float _MaxHP = 100;
/// <summary>
/// Gets or sets the max HP.
/// </summary>
public float MaxHP
{
get { return _MaxHP; }
set
{
_MaxHP = value;
if (HP == 0)
HP = value;
}
}
protected int hp = 0;
protected int defence = 0;
protected int stepsTaken = 0;
protected int distanceToTarget = 0;
@@ -65,7 +84,8 @@ namespace DepthsBelow.Component
return panic + GetPenalty(stepsTaken) + (int)(GetPenalty(distance) / 2);
}
public Stat(Entity parent) : base (parent)
public Stat(Entity parent)
: base (parent)
{
}
+21 -19
View File
@@ -32,7 +32,8 @@ namespace DepthsBelow
public static MouseInput MouseInput;
public static KeyboardInput KeyboardInput;
public List<Soldier> Squad;
public List<Soldier> Squad;
public DynamicGroupManager GroupManager;
public List<SmallEnemy> Swarm;
public List<Shot> Volley;
public static Map Map;
@@ -42,20 +43,16 @@ namespace DepthsBelow
public Core()
{
GraphicsDeviceManager = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
GraphicsDeviceManager.PreferredBackBufferHeight = 720;
GraphicsDeviceManager.IsFullScreen = false;
//graphics.SynchronizeWithVerticalRetrace = false;
this.IsFixedTimeStep = false;
GraphicsDeviceManager.ApplyChanges();
this.IsFixedTimeStep = false;
this.IsMouseVisible = true;
GameServices.AddService<GraphicsDevice>(GraphicsDevice);
GameServices.AddService<ContentManager>(Content);
Content.RootDirectory = "Content";
}
/// <summary>
@@ -66,19 +63,21 @@ namespace DepthsBelow
/// </summary>
protected override void Initialize()
{
Lua = new Lua();
// TODO: Add your initialization logic here
EntityManager = new EntityManager();
TurnManager = new TurnManager(new string[] { "Player", "Computer" });
GameServices.AddService<GraphicsDevice>(GraphicsDevice);
GameServices.AddService<ContentManager>(Content);
Lua = new Lua();
EntityManager = new EntityManager();
TurnManager = new TurnManager(new string[] { "Player", "Computer" });
Camera = new Camera(this);
Interface = new Interface(this);
Squad = new List<Soldier>();
Swarm = new List<SmallEnemy>();
Volley = new List<Shot>();
Interface = new Interface(this);
Squad = new List<Soldier>();
Swarm = new List<SmallEnemy>();
Volley = new List<Shot>();
base.Initialize();
}
@@ -94,6 +93,8 @@ namespace DepthsBelow
Map = Content.Load<Map>("maps/Cave.Level1");
// Load map objects
Map.ParseObjects(this);
GroupManager = new DynamicGroupManager(Squad.Cast<Entity>().ToList(), (float)Grid.TileSize * 1.5f);
Interface.CreateUnitFrames(Squad);
// TODO: use this.Content to load your game content here
Soldier.LoadContent();
@@ -139,6 +140,7 @@ namespace DepthsBelow
EntityManager.Update(gameTime);
Interface.Update(gameTime);
GUIManager.Update(gameTime);
base.Update(gameTime);
@@ -121,6 +121,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Camera.cs" />
<Compile Include="DynamicGroupManager.cs" />
<Compile Include="TurnManager.cs" />
<Compile Include="CustomExtensions.cs" />
<Compile Include="EntityManager.cs" />
+106
View File
@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace DepthsBelow
{
public class DynamicGroupManager
{
public class Group
{
public List<Entity> Entities;
public float Panic;
}
private List<Entity> entities;
public float MaxRange;
public List<Group> Groups;
public DynamicGroupManager(List<Entity> entities, float maxRange)
{
this.entities = entities;
this.MaxRange = maxRange;
UpdateGroups();
}
public void UpdateGroups()
{
if (Groups == null)
Groups = new List<Group>();
var newGroups = CreateGroups(MaxRange);
foreach (var newGroup in newGroups)
{
foreach (var entity in newGroup.Entities)
{
Group oldGroup = null;
// Find the group the entity belonged to before
foreach (var group in Groups)
{
if (group.Entities.Contains(entity))
{
oldGroup = group;
break;
}
}
if (oldGroup != null)
newGroup.Panic += oldGroup.Panic / oldGroup.Entities.Count;
else
newGroup.Panic = 10;
}
}
Groups = newGroups;
}
private List<Group> CreateGroups(float maxRange)
{
var alreadyGrouped = new List<Entity>();
var groups = new List<Group>();
for (int index = 0; index < entities.Count; index++)
{
var soldier = entities[index];
if (!alreadyGrouped.Contains(soldier))
{
var group = new List<Entity>();
GetNearChain(ref group, soldier, maxRange);
alreadyGrouped.AddRange(group);
if (group.Count > 0)
groups.Add(new Group() { Entities = group });
}
}
return groups;
}
// Get all entities who are close to each other in a chain
private void GetNearChain(ref List<Entity> group, Entity entity, float maxRange)
{
for (int index = 0; index < entities.Count; index++)
{
var nearSoldier = entities[index];
if (!group.Contains(nearSoldier))
{
float distance = Vector2.Distance(nearSoldier.Transform.World + nearSoldier.Transform.World.Origin,
entity.Transform.World + entity.Transform.World.Origin);
if (distance <= maxRange)
{
group.Add(nearSoldier);
GetNearChain(ref group, nearSoldier, maxRange);
}
}
}
}
}
}
+13
View File
@@ -45,6 +45,19 @@ namespace DepthsBelow
set { this.Transform.Grid.Y = value; }
}
/// <summary>
/// Storage for property data
/// </summary>
public Dictionary<string, object> Properties = new Dictionary<string, object>();
/// <summary>
/// Shorthand for frame properties.
/// </summary>
public object this[string key]
{
get { return Properties[key]; }
set { Properties[key] = value; }
}
/// <summary>
/// Creates a game object and adds it to the referenced entity manager.
/// </summary>
+3 -3
View File
@@ -29,10 +29,10 @@ namespace DepthsBelow.GUI
}
public Button(Frame parent)
: this()
public Button(Frame parent)
: base(parent)
{
this.Parent = parent;
}
public override void Update(GameTime gameTime)
+145 -41
View File
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
@@ -81,16 +83,17 @@ namespace DepthsBelow.GUI
/// </summary>
public Rectangle Rectangle;
/// <summary>
/// Absolute rectangle of the frame. Takes parent frame positions in consideration.
/// Absolute rectangle of the frame.
/// Takes parent frame positions in consideration and converts negative widths and heights.
/// </summary>
public Rectangle AbsoluteRectangle
{
get
{
if (Parent != null)
return new Rectangle(Parent.AbsoluteRectangle.X + Rectangle.X, Parent.AbsoluteRectangle.Y + Rectangle.Y, Rectangle.Width, Rectangle.Height);
return Utility.MakeRectanglePositive(new Rectangle(Parent.AbsoluteRectangle.X + Rectangle.X, Parent.AbsoluteRectangle.Y + Rectangle.Y, Rectangle.Width, Rectangle.Height));
else
return Rectangle;
return Utility.MakeRectanglePositive(Rectangle);
}
}
/// <summary>
@@ -101,10 +104,16 @@ namespace DepthsBelow.GUI
/// Texture color tint.
/// </summary>
public Color Color;
public bool _Visible = true;
/// <summary>
/// If the frame is visible or not.
/// </summary>
public bool Visible = true;
public bool Visible
{
get { return (Parent != null) ? _Visible && Parent.Visible : _Visible; }
set { _Visible = value; }
}
/// <summary>
/// The layer of the frame.
@@ -132,47 +141,142 @@ namespace DepthsBelow.GUI
/// </summary>
public List<Frame> Children;
/// <summary>
/// Storage for property data
/// </summary>
public Dictionary<string, object> Properties = new Dictionary<string, object>();
/// <summary>
/// Shorthand for frame properties.
/// </summary>
public object this[string key]
{
get { return Properties[key]; }
set { Properties[key] = value; }
}
/// <summary>
/// Controls whether mouse events can be handled by the frame.
/// </summary>
public bool MouseEnabled = false;
#region Events
/// <summary>
/// Handler for click events.
/// </summary>
/// <param name="frame">The frame.</param>
/// <param name="args">The <see cref="GUIManager.MouseEventArgs" /> instance containing the event data.</param>
public delegate void OnClickHandler(Frame frame, GUIManager.MouseEventArgs args);
/// <summary>
/// Occurs when the frame is clicked inside it's bounding rectangle.
/// </summary>
public event OnClickHandler OnClick;
/// <summary>
/// Gets the number of subscribers to the <see cref="OnClickHandler" /> event.
/// </summary>
public int OnClickCount
{
get { return (OnClick != null) ? OnClick.GetInvocationList().Length : 0; }
}
/// <summary>
/// <see cref="OnClickHandler" /> event arguments.
/// </summary>
public class OnClickArgs : EventArgs
{
/// <summary>
/// The position of the click relative to the frame position.
/// </summary>
public Point Position;
/// <summary>
/// The time of the click, since the start of the program.
/// </summary>
public TimeSpan Time;
}
/// <summary>
/// Handler for click events.
/// Handler for press events.
/// </summary>
/// <param name="frame">The clicked frame.</param>
/// <param name="e">The <see cref="OnClickArgs" /> instance containing the event data.</param>
public delegate void OnClickHandler(Frame frame, OnClickArgs e);
/// <param name="frame">The frame.</param>
/// <param name="args">The <see cref="GUIManager.MouseEventArgs" /> instance containing the event data.</param>
public delegate void OnPressHandler(Frame frame, GUIManager.MouseEventArgs args);
/// <summary>
/// Raise an <see cref="OnClick" /> event on the frame.
/// Occurs when the frame is clicked inside it's bounding rectangle.
/// </summary>
/// <param name="e">The <see cref="OnClickArgs" /> instance containing the event data.</param>
public void Click(OnClickArgs e)
public event OnPressHandler OnPress;
/// <summary>
/// Handler for release events.
/// </summary>
/// <param name="frame">The frame.</param>
/// <param name="args">The <see cref="GUIManager.MouseEventArgs" /> instance containing the event data.</param>
public delegate void OnReleaseHandler(Frame frame, GUIManager.MouseEventArgs args);
/// <summary>
/// Occurs when the frame is clicked inside it's bounding rectangle.
/// </summary>
public event OnReleaseHandler OnRelease;
/// <summary>
/// Handler for mouse over events.
/// </summary>
/// <param name="frame">The frame.</param>
/// <param name="args">The <see cref="GUIManager.MouseEventArgs" /> instance containing the event data.</param>
public delegate void OnMouseOverHandler(Frame frame, GUIManager.MouseEventArgs args);
/// <summary>
/// Occurs when the frame is clicked inside it's bounding rectangle.
/// </summary>
public event OnMouseOverHandler OnMouseOver;
/// <summary>
/// Handler for mouse out events.
/// </summary>
/// <param name="frame">The frame.</param>
/// <param name="args">The <see cref="GUIManager.MouseEventArgs" /> instance containing the event data.</param>
public delegate void OnMouseOutHandler(Frame frame, GUIManager.MouseEventArgs args);
/// <summary>
/// Occurs when the frame is clicked inside it's bounding rectangle.
/// </summary>
public event OnMouseOutHandler OnMouseOut;
/// <summary>
/// Raises the specified event by name.
/// </summary>
/// <param name="eventName">Name of the event.</param>
/// <param name="eventArgs">The <see cref="EventArgs" /> instance containing the event data.</param>
/// <returns>Returns true if any event was raised.</returns>
public bool Raise(string eventName, EventArgs eventArgs)
{
if (OnClick != null)
OnClick(this, e);
// Get the event field info
var fieldInfo = this.GetType().GetField(eventName, BindingFlags.NonPublic | BindingFlags.Instance);
// If the event exists
if (fieldInfo != null)
{
var eventDelegate = (MulticastDelegate)fieldInfo.GetValue(this);
// If there's any subscribed events...
if (eventDelegate != null)
{
// Invoke their raise methods
foreach (var handler in eventDelegate.GetInvocationList())
{
try
{
handler.Method.Invoke(handler.Target, new object[] { this, eventArgs });
}
catch (Exception)
{
return false;
}
}
return true;
}
return false;
}
return false;
}
/// <summary>
/// Gets the subscriber count for a specific event.
/// </summary>
/// <param name="eventName">Name of the event.</param>
/// <returns>Returns the number of subscribers of the event.</returns>
public int GetSubscriberCount(string eventName)
{
// Get the event field info
var fieldInfo = this.GetType().GetField(eventName, BindingFlags.NonPublic | BindingFlags.Instance);
// If the event exists
if (fieldInfo != null)
{
var eventDelegate = (MulticastDelegate)fieldInfo.GetValue(this);
// If there's any subscribed events...
if (eventDelegate != null)
return eventDelegate.GetInvocationList().Length;
return 0;
}
return 0;
}
#endregion
@@ -189,7 +293,7 @@ namespace DepthsBelow.GUI
this.Children = new List<Frame>();
UID = GUIManager.Add(this);
this.UID = GUIManager.Add(this);
}
/// <summary>
@@ -258,7 +362,7 @@ namespace DepthsBelow.GUI
{
if (OnClick != null)
{
var args = new OnClickArgs()
var args = new MouseEventArgs()
{
Position = new Point(ms.X - AbsoluteRectangle.X, ms.Y - AbsoluteRectangle.Y),
Time = gameTime.TotalGameTime
@@ -270,19 +374,19 @@ namespace DepthsBelow.GUI
lastMouseState = ms;*/
foreach (var child in Children)
child.Update(gameTime);
/*foreach (var child in Children)
child.Update(gameTime);*/
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (Visible)
{
{
if (Texture != null)
spriteBatch.Draw(Texture, AbsoluteRectangle, Color);
foreach (var child in Children)
child.Draw(spriteBatch);
/*foreach (var child in Children)
child.Draw(spriteBatch);*/
}
}
}
+4 -4
View File
@@ -29,9 +29,9 @@ namespace DepthsBelow.GUI
}
public Text(Frame parent)
: this()
: base(parent)
{
this.Parent = parent;
this.Color = Color.White;
}
/// <summary>
@@ -47,8 +47,8 @@ namespace DepthsBelow.GUI
{
base.Draw(spriteBatch);
if (Parent.Visible && this.Visible && Font != null)
spriteBatch.DrawString(Font, Value, new Vector2(Rectangle.X + Parent.Rectangle.X, Rectangle.Y + Parent.Rectangle.Y), Color);
if (Visible && Font != null)
spriteBatch.DrawString(Font, Value, new Vector2(Rectangle.X + Parent.AbsoluteRectangle.X, Rectangle.Y + Parent.AbsoluteRectangle.Y), Color);
}
}
}
+42 -14
View File
@@ -6,18 +6,35 @@ using System.Text;
using DepthsBelow.GUI;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace DepthsBelow
{
static class GUIManager
public static class GUIManager
{
/// <summary>
/// GUI mouse event arguments.
/// </summary>
public class MouseEventArgs : EventArgs
{
/// <summary>
/// The XNA mouse state.
/// </summary>
public MouseState MouseState;
/// <summary>
/// The time of the click, since the start of the program.
/// </summary>
public TimeSpan Time;
}
public static List<Frame> Frames = new List<Frame>();
private static int uidIndex = 0;
public static int Add(Frame frame)
{
Frames.Add(frame);
return uidIndex++;
return CreateUID();
}
public static void Remove(Frame frame)
@@ -25,24 +42,35 @@ namespace DepthsBelow
Frames.Remove(frame);
}
public static void Click(Point position, TimeSpan time)
public static int CreateUID()
{
var clickRectangle = new Rectangle(position.X, position.Y, 1, 1);
return uidIndex++;
}
// Create a list of all frames which have an OnClick handler and intersects with the click position
var intersections = Frames.Where(frame => frame.OnClickCount > 0).Where(frame => clickRectangle.Intersects(frame.AbsoluteRectangle)).ToList();
/// <summary>
/// Calculates which frames are intersecting a point.
/// </summary>
/// <param name="point">A point on the screen.</param>
/// <returns>Returns a list of frames intersecting the point.</returns>
public static List<Frame> FramesIntersectingPoint(Point point)
{
var rect = new Rectangle(point.X, point.Y, 1, 1);
return Frames.Where(frame => rect.Intersects(frame.AbsoluteRectangle)).ToList();
}
public static bool RaiseAt(string eventName, EventArgs eventArgs, Point position)
{
// Create a list of all frames which intersects with the click position
var intersections = FramesIntersectingPoint(position);
// Filter it by event
intersections = intersections.Where(frame => frame.GetSubscriberCount(eventName) > 0).ToList();
// Get the topmost frame of that list
var topFrame = GetTopFrame(intersections);
if (topFrame != null)
{
var e = new Frame.OnClickArgs()
{
Position = position,
Time = time
};
topFrame.Click(e);
}
return topFrame.Raise(eventName, eventArgs);
else
return false;
}
/// <summary>
+301 -49
View File
@@ -6,6 +6,7 @@ using DepthsBelow.GUI;
using Microsoft.Xna.Framework;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace DepthsBelow
{
@@ -13,10 +14,132 @@ namespace DepthsBelow
{
Core core;
/// <summary>
/// The master frame covering the whole game screen. Parent of all frames.
/// This frame handles all mouse interaction with the game world
/// </summary>
public Frame UIParent;
public List<Frame> PanicFrames = new List<Frame>();
public List<Frame> UnitFrames = new List<Frame>();
public Dictionary<Soldier, Frame> SoldierToFrame = new Dictionary<Soldier, Frame>();
Random random = new Random();
public Interface(Core core)
{
this.core = core;
UIParent = new Frame();
UIParent.Width = GameServices.GetService<GraphicsDevice>().Viewport.Width;
UIParent.Height = GameServices.GetService<GraphicsDevice>().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;
// OnClick
UIParent.OnClick += 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);
// 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 units in the rectangle
foreach (var soldier in core.Squad)
{
if (mouseWorldRectangle.Intersects(soldier.GetComponent<Component.Collision>().Rectangle))
{
soldier.Selected = true;
foreach (var unitFrame in UnitFrames)
{
if (unitFrame["soldier"] == soldier)
unitFrame.Color = Color.Blue;
}
}
}
// Send orders with right click
if (ks.IsKeyDown(Keys.LeftControl))
foreach (var unit in core.Squad)
if (unit.Selected)
unit.GetComponent<Component.PathFinder>().Goal = Grid.WorldToGrid(mouseWorldPos);
// Hide the selection rectangle
//selectionRectangle = Rectangle.Empty;
};
// 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
var selectFrame = (GUI.Frame)frame["selectionFrame"];
if (!selectFrame.Visible)
{
selectFrame.X = (int)mousePos.X;
selectFrame.Y = (int)mousePos.Y;
selectFrame.Visible = true;
}
};
// OnRelease
UIParent.OnRelease += delegate(Frame frame, GUIManager.MouseEventArgs args)
{
// Show the selection frame
var selectFrame = (GUI.Frame)frame["selectionFrame"];
if (selectFrame.Visible)
{
var intersectionRectangle = core.Camera.ScreenToWorld(selectFrame.AbsoluteRectangle);
// Select all units in the rectangle
foreach (var soldier in core.Squad)
{
if (intersectionRectangle.Intersects(soldier.GetComponent<Component.Collision>().Rectangle))
{
soldier.Selected = true;
foreach (var unitFrame in UnitFrames)
{
if (unitFrame["soldier"] == soldier)
unitFrame.Color = Color.Blue;
}
}
}
selectFrame.Visible = false;
}
};
var leftEdge = new Frame(UIParent);
leftEdge.Width = 20;
leftEdge.Height = GameServices.GetService<GraphicsDevice>().Viewport.Height;
// Test GUI frames
/*var frame = new GUI.Frame()
{
@@ -39,30 +162,29 @@ namespace DepthsBelow
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)
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.OnClickArgs args)
unit2.OnClick += delegate(Frame frame, Frame.MouseEventArgs args)
{
frame.Color = Color.Red;
};*/
var frame1 = new GUI.Frame();
/*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)
frame1.OnClick += delegate(Frame frame, Frame.MouseEventArgs args)
{
if (frame.Color == Color.Red)
frame.Color = Color.Green;
@@ -76,13 +198,6 @@ namespace DepthsBelow
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;
@@ -92,71 +207,208 @@ namespace DepthsBelow
frame2.Height = 100;
frame2.X = 50;
frame2.Y = 50;
frame2.OnClick += delegate(Frame frame, Frame.OnClickArgs args)
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();
var frame = new GUI.Frame(UIParent);
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;
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;
return frame;
}
private GUI.Frame CreateUnitFrame(string unitName)
private GUI.Frame CreateUnitFrame(Soldier soldier)
{
var frame = new GUI.Frame();
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 = unitName;
nameText.X = 4;
nameText.Y = 1;
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 healthBg = new GUI.Frame(frame);
healthBg.SetTexture("images/GUI/health_background");
healthBg.Width = 136;
healthBg.Height = 13;
healthBg.X = 3;
healthBg.Y = 19;
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(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;
var healthBar = new GUI.Frame(healthBarBg);
healthBar.SetTexture("images/GUI/bar_solid");
healthBar.Color = Color.Red;
healthBar.Width = (int)((healthBarBg.Width - 2) * (soldier.GetComponent<Component.Stat>().HP / soldier.GetComponent<Component.Stat>().MaxHP));
healthBar.Height = 11;
healthBar.X = 1;
healthBar.Y = 1;
frame["healthBar"] = healthBar;
return frame;
}
public void CreateUnitFrames(List<Soldier> squad)
{
// TODO: ForEach squad in Squads...
/*GUI.Frame lastFrame = null;
foreach (Soldier soldier in squad)
{
// TODO: Remove this test ;)
soldier.GetComponent<Component.Stat>().HP = random.Next(0, (int) soldier.GetComponent<Component.Stat>().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<Component.Stat>().HP = random.Next(0, (int)soldier.GetComponent<Component.Stat>().MaxHP - 1);
var uFrame = CreateUnitFrame(soldier);
uFrame["soldier"] = soldier;
soldier["unitFrame"] = uFrame;
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);
}
}
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];
var pFrameBarBg = (GUI.Frame)pFrame["panicBarBg"];
var pFrameBar = (GUI.Frame)pFrame["panicBar"];
pFrameBar.Width = (int)(pFrameBarBg.Width * (group.Panic / 100f));
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;
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;
}
UpdateUnitFrames();
}
}
}
+100 -2
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
@@ -22,7 +23,85 @@ namespace DepthsBelow
this.core = core;
}
public void Update(GameTime gameTime)
/*public List<List<Soldier>> GetGroups(List<Soldier> soldiers)
{
var ungrouped = soldiers.ToList();
var groups = new List<List<Soldier>>();
for (int index = 0; index < soldiers.Count; index++)
{
var checkingSoldier = soldiers[index];
var group = new List<Soldier>();
for (int i = 0; i < soldiers.Count; i++)
{
var soldier = soldiers[i];
if (ungrouped.Contains(soldier))
{
float distance = Vector2.Distance(checkingSoldier.Transform.World + checkingSoldier.Transform.World.Origin,
soldier.Transform.World + soldier.Transform.World.Origin);
if (distance <= ((float) Grid.TileSize * 1f))
{
ungrouped.Remove(soldier);
group.Add(soldier);
}
}
}
if (group.Count > 0)
groups.Add(group);
}
return groups;
}*/
// Get a list of dynamic soldier groups
public List<List<Soldier>> GetGroups(List<Soldier> soldiers, float maxRange)
{
var alreadyGrouped = new List<Soldier>();
var groups = new List<List<Soldier>>();
for (int index = 0; index < soldiers.Count; index++)
{
var soldier = soldiers[index];
if (!alreadyGrouped.Contains(soldier))
{
var group = new List<Soldier>();
GetNearChain(ref group, soldiers, soldier, maxRange);
alreadyGrouped.AddRange(group);
if (group.Count > 0)
groups.Add(group);
}
}
return groups;
}
// Get all soldiers who are close to each other in a chain
public void GetNearChain(ref List<Soldier> group, List<Soldier> soldiers, Soldier soldier, float maxRange)
{
for (int index = 0; index < soldiers.Count; index++)
{
var nearSoldier = soldiers[index];
if (!group.Contains(nearSoldier))
{
float distance = Vector2.Distance(nearSoldier.Transform.World + nearSoldier.Transform.World.Origin,
soldier.Transform.World + soldier.Transform.World.Origin);
if (distance <= maxRange)
{
group.Add(nearSoldier);
GetNearChain(ref group, soldiers, nearSoldier, maxRange);
}
}
}
}
private DynamicGroupManager groupManager;
public void Update(GameTime gameTime)
{
KeyboardState ks = Keyboard.GetState();
@@ -30,6 +109,25 @@ namespace DepthsBelow
if (ks.IsKeyUp(Keys.R) && lastKeyboardState.IsKeyDown(Keys.R))
{
core.Lua.Reload();
}
// Debug test: grouping
if (ks.IsKeyUp(Keys.K) && lastKeyboardState.IsKeyDown(Keys.K))
{
if (groupManager == null)
groupManager = new DynamicGroupManager(core.Squad.Cast<Entity>().ToList(), Grid.TileSize * 1.5f);
groupManager.UpdateGroups();
//var groups = GetGroups(core.Squad, (float)Grid.TileSize * 1.5f);
var groups = groupManager.Groups;
foreach (var group in groups)
{
Debug.WriteLine("Group #" + groups.IndexOf(group) + " Panic: " + group.Panic);
foreach (var entity in group.Entities)
{
var soldier = (Soldier)entity;
Debug.WriteLine(soldier.Name + " " + soldier.GetHashCode());
}
}
}
// Next turn
+1
View File
@@ -73,6 +73,7 @@ namespace DepthsBelow
if (mapObject.Type == "SquadStart")
{
var soldier = new Soldier(core.EntityManager, ref core.Squad);
soldier.Name = "Derp";
// 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);
+61 -7
View File
@@ -25,6 +25,8 @@ namespace DepthsBelow
bool checkingDirection = false;
bool readjust = false;
private Point pressLocation;
public MouseInput(Core core)
{
@@ -43,9 +45,50 @@ namespace DepthsBelow
gridTexture.SetData(new Color[] { Color.White });
}
public void OnPress(MouseState ms, GameTime gameTime)
{
pressLocation = new Point(ms.X, ms.Y);
var mouseEvent = new GUIManager.MouseEventArgs()
{
MouseState = ms,
Time = gameTime.TotalGameTime
};
bool handledByUI = GUIManager.RaiseAt("OnPress", mouseEvent, pressLocation);
if (handledByUI)
return;
// If the mouse event is above a GUI frame that handles mouse events, do nothing
//if (GUIManager.FramesIntersectingPoint(mousePos).Any(frame => frame.MouseEnabled))
// return;
}
public void OnRelease(MouseState ms, GameTime gameTime)
{
var mouseEvent = new GUIManager.MouseEventArgs()
{
MouseState = ms,
Time = gameTime.TotalGameTime
};
bool handledByUI = GUIManager.RaiseAt("OnRelease", mouseEvent, pressLocation);
if (handledByUI)
return;
}
public void OnClick(MouseState ms, GameTime gameTime)
{
GUIManager.Click(new Point(ms.X, ms.Y), gameTime.TotalGameTime);
var mouseEvent = new GUIManager.MouseEventArgs()
{
MouseState = ms,
Time = gameTime.TotalGameTime
};
bool handledByUI = GUIManager.RaiseAt("OnClick", mouseEvent, new Point(ms.X, ms.Y));
if (handledByUI)
return;
}
public void Update(GameTime gameTime)
@@ -54,14 +97,24 @@ namespace DepthsBelow
Vector2 mouseWorldPos = core.Camera.ScreenToWorld(new Vector2(ms.X, ms.Y));
Rectangle mouseWorldRectangle = new Rectangle((int)mouseWorldPos.X, (int)mouseWorldPos.Y, 1, 1);
KeyboardState ks = Keyboard.GetState();
// OnPress event
if (
(ms.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released)
|| (ms.RightButton == ButtonState.Pressed && lastMouseState.RightButton == ButtonState.Released)
)
OnPress(ms, gameTime);
// OnClick event
// OnRelease event
if (
(ms.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed)
|| (ms.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed)
)
{
OnClick(ms, gameTime);
OnRelease(ms, gameTime);
}
// Tooltip stuff
var tooltip = core.Lua.GetObject<GUI.Frame>("ToolTip");
@@ -87,7 +140,7 @@ namespace DepthsBelow
if (core.TurnManager.CurrentTurn == core.TurnManager["Player"])
{
// Selection rectangle
if (ms.LeftButton == ButtonState.Pressed)
/*if (ms.LeftButton == ButtonState.Pressed)
{
if (selectionRectangle == Rectangle.Empty)
@@ -118,9 +171,10 @@ namespace DepthsBelow
readjust = false;
}
}
}
}*/
// When the mouse is released
if (ms.LeftButton == ButtonState.Released && selectionRectangle != Rectangle.Empty)
/*if (ms.LeftButton == ButtonState.Released && selectionRectangle != Rectangle.Empty)
{
// Deselect all units
if (!ks.IsKeyDown(Keys.LeftControl))
@@ -138,7 +192,7 @@ namespace DepthsBelow
// Hide the selection rectangle
selectionRectangle = Rectangle.Empty;
}
}*/
// Send orders with right click
if (ms.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed)
+4 -3
View File
@@ -11,8 +11,8 @@ namespace DepthsBelow
public class Soldier : Entity
{
public static Texture2D Texture;
public Color Color;
public static Point Origin;
public Color Color;
public string Name;
private bool _selected;
public List<Soldier> Squad;
@@ -66,7 +66,8 @@ namespace DepthsBelow
var stat = new Component.Stat(this)
{
Life = 10,
MaxHP = 100,
//Life = 10,
Defence = 10,
Strength = 10,
GetAim = 10,
+38
View File
@@ -63,5 +63,43 @@ namespace DepthsBelow
angle, Vector2.Zero, new Vector2(length, width),
SpriteEffects.None, 0);
}
private static Texture2D solidTexture = null;
/// <summary>
/// Creates a 1x1 solid white XNA texture.
/// </summary>
/// <returns>Returns a 1x1 solid white Texture2D object.</returns>
public static Texture2D GetSolidTexture()
{
if (solidTexture == null)
{
solidTexture = new Texture2D(GameServices.GetService<GraphicsDevice>(), 1, 1);
solidTexture.SetData(new Color[] { Color.White });
}
return solidTexture;
}
/// <summary>
/// Converts rectangles with negative sizes to positive sizes with its position offset.
/// </summary>
/// <param name="rect">The rectangle with potentially negative sizes.</param>
/// <returns>Returns a rectangle with positive sizes.</returns>
public static Rectangle MakeRectanglePositive(Rectangle rect)
{
if (rect.Width < 0)
{
rect.X += rect.Width;
rect.Width = -rect.Width;
}
if (rect.Height < 0)
{
rect.Y += rect.Height;
rect.Height = -rect.Height;
}
return rect;
}
}
}