From e2ba79a5393759fedaf13f5fdc352f542ea4bfd0 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Mon, 22 Mar 2010 18:43:52 +1300 Subject: [PATCH] spatial bin index for actors --- OpenRA.Game/OpenRA.Game.csproj | 1 + OpenRA.Game/Orders/UnitOrderGenerator.cs | 13 +++-- OpenRA.Game/Traits/World/SpatialBins.cs | 74 ++++++++++++++++++++++++ mods/ra/rules.yaml | 1 + 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 OpenRA.Game/Traits/World/SpatialBins.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 4e139c17a4..fe3a253a0e 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -116,6 +116,7 @@ + diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index f9c6612700..3aa2917822 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -51,15 +51,16 @@ namespace OpenRA.Orders return ChooseCursor(world, mi); } - string ChooseCursor( World world, MouseInput mi ) + string ChooseCursor(World world, MouseInput mi) { + + var p = Game.controller.MousePosition; + var c = Order(world, p.ToInt2(), mi) + .Select(o => CursorForOrderString(o.OrderString, o.Subject, o.TargetLocation)) + .FirstOrDefault(a => a != null); + using (new PerfSample("cursor")) { - var p = Game.controller.MousePosition; - var c = Order(world, p.ToInt2(), mi) - .Select(o => CursorForOrderString(o.OrderString, o.Subject, o.TargetLocation)) - .FirstOrDefault(a => a != null); - return c ?? (world.SelectActorsInBox(Game.CellSize * p, Game.CellSize * p).Any() diff --git a/OpenRA.Game/Traits/World/SpatialBins.cs b/OpenRA.Game/Traits/World/SpatialBins.cs new file mode 100644 index 0000000000..ddfac0fbec --- /dev/null +++ b/OpenRA.Game/Traits/World/SpatialBins.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; + +namespace OpenRA.Traits +{ + class SpatialBinsInfo : ITraitInfo + { + public readonly int BinSize = 8; + public object Create(Actor self) { return new SpatialBins( self, this ); } + } + + class SpatialBins : ITick + { + List[,] bins; + int scale; + + public SpatialBins(Actor self, SpatialBinsInfo info) + { + bins = new List[ + self.World.Map.MapSize / info.BinSize, + self.World.Map.MapSize / info.BinSize]; + + scale = Game.CellSize * info.BinSize; + } + + public void Tick(Actor self) + { + for (var j = 0; j < bins.GetUpperBound(1); j++) + for (var i = 0; i < bins.GetUpperBound(0); i++) + bins[i, j] = new List(); + + foreach (var a in self.World.Actors) + { + if (a.Location.X >= self.World.Map.MapSize + || a.Location.Y >= self.World.Map.MapSize) + continue; + + var bounds = a.GetBounds(true); + var i1 = (int)bounds.Left / scale; + var i2 = (int)bounds.Right / scale; + var j1 = (int)bounds.Top / scale; + var j2 = (int)bounds.Bottom / scale; + + for (var j = j1; j <= j2; j++) + for (var i = i1; i <= i2; i++) + bins[i, j].Add(a); + } + } + + IEnumerable ActorsInBins(int i1, int i2, int j1, int j2) + { + for (var j = j1; j <= j2; j++) + for (var i = i1; i <= i2; i++) + foreach (var a in bins[i, j]) + yield return a; + } + + public IEnumerable ActorsInBox(int2 a, int2 b) + { + var r = RectangleF.FromLTRB( a.X, a.Y, b.X, b.Y ); + + return ActorsInBins( + a.X / scale, + a.Y / scale, + b.X / scale, + b.Y / scale) + .Distinct() + .Where(u => u.GetBounds(true).IntersectsWith(r)); + } + } +} diff --git a/mods/ra/rules.yaml b/mods/ra/rules.yaml index 07449e9e05..be5e0e20b4 100755 --- a/mods/ra/rules.yaml +++ b/mods/ra/rules.yaml @@ -272,6 +272,7 @@ World: SpawnMapActors: SpawnDefaultUnits: EvaAlerts: + SpatialBins: MGG: GeneratesGap: