diff --git a/OpenRA.Game/WorldUtils.cs b/OpenRA.Game/WorldUtils.cs index 7769a698ab..c4aa3f06cc 100755 --- a/OpenRA.Game/WorldUtils.cs +++ b/OpenRA.Game/WorldUtils.cs @@ -58,14 +58,37 @@ namespace OpenRA public static IEnumerable FindTilesInCircle(this World world, CPos a, int r) { - var min = world.ClampToWorld(a - new CVec(r, r)); - var max = world.ClampToWorld(a + new CVec(r, r)); - for (var j = min.Y; j <= max.Y; j++) - for (var i = min.X; i <= max.X; i++) - if (r * r >= (new CPos(i, j) - a).LengthSquared) - yield return new CPos(i, j); + if (r > TilesByDistance.Length) + throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxRange)); + + for(var i = 0; i < r; i++) + { + foreach(var offset in TilesByDistance[i]) + { + var t = offset + a; + if (world.Map.Bounds.Contains(t.X, t.Y)) + yield return t; + } + } } + static List[] InitTilesByDistance(int max) + { + var ts = new List[max+1]; + for (var i = 0; i < max+1; i++) + ts[i] = new List(); + + for (var j = -max; j <= max; j++) + for (var i = -max; i <= max; i++) + if (max * max >= i * i + j * j) + ts[(int)Math.Ceiling(Math.Sqrt(i*i + j*j))].Add(new CVec(i,j)); + + return ts; + } + + const int MaxRange = 50; + static List[] TilesByDistance = InitTilesByDistance(MaxRange); + public static string GetTerrainType(this World world, CPos cell) { var custom = world.Map.CustomTerrain[cell.X, cell.Y];