From af0e948a67a8a101d3cf1ec9a6aadd4f23740d00 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 21 Sep 2013 22:55:41 +1200 Subject: [PATCH 1/6] Use map.Contains for the observer shroud check. Checking against the bounds directly is no longer valid. --- OpenRA.Mods.RA/ShroudRenderer.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/ShroudRenderer.cs b/OpenRA.Mods.RA/ShroudRenderer.cs index 302d466984..0d5b45ff12 100644 --- a/OpenRA.Mods.RA/ShroudRenderer.cs +++ b/OpenRA.Mods.RA/ShroudRenderer.cs @@ -177,19 +177,19 @@ namespace OpenRA.Mods.RA return useExtendedIndex ? u ^ uside : u & 0x0F; } - static int ObserverShroudedEdges(CPos p, Rectangle bounds, bool useExtendedIndex) + static int ObserverShroudedEdges(Map map, CPos p, bool useExtendedIndex) { var u = 0; - if (p.Y == bounds.Top) u |= 0x13; - if (p.X == bounds.Right - 1) u |= 0x26; - if (p.Y == bounds.Bottom - 1) u |= 0x4C; - if (p.X == bounds.Left) u |= 0x89; + if (!map.Contains(p + new CVec(0, -1))) u |= 0x13; + if (!map.Contains(p + new CVec(1, 0))) u |= 0x26; + if (!map.Contains(p + new CVec(0, 1))) u |= 0x4C; + if (!map.Contains(p + new CVec(-1, 0))) u |= 0x89; var uside = u & 0x0F; - if (p.X == bounds.Left && p.Y == bounds.Top) u |= 0x01; - if (p.X == bounds.Right - 1 && p.Y == bounds.Top) u |= 0x02; - if (p.X == bounds.Right - 1 && p.Y == bounds.Bottom - 1) u |= 0x04; - if (p.X == bounds.Left && p.Y == bounds.Bottom - 1) u |= 0x08; + if (!map.Contains(p + new CVec(-1, -1))) u |= 0x01; + if (!map.Contains(p + new CVec(1, -1))) u |= 0x02; + if (!map.Contains(p + new CVec(1, 1))) u |= 0x04; + if (!map.Contains(p + new CVec(-1, 1))) u |= 0x08; return useExtendedIndex ? u ^ uside : u & 0x0F; } @@ -229,7 +229,7 @@ namespace OpenRA.Mods.RA foreach (var cell in map.Cells) { var t = tiles[cell]; - var shrouded = ObserverShroudedEdges(t.Position, map.Bounds, info.UseExtendedIndex); + var shrouded = ObserverShroudedEdges(map, t.Position, info.UseExtendedIndex); t.Shroud = shrouded != 0 ? shroudSprites[t.Variant * variantStride + spriteMap[shrouded]] : null; t.Fog = shrouded != 0 ? fogSprites[t.Variant * variantStride + spriteMap[shrouded]] : null; From a30c8b53a7ed8735ec55688ec0769774af76fb4a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 30 Jun 2014 11:25:39 +1200 Subject: [PATCH 2/6] Add support for diamond cell grids. --- OpenRA.Game/Graphics/Minimap.cs | 76 ++++++++++------ OpenRA.Game/Graphics/TerrainRenderer.cs | 9 +- OpenRA.Game/Graphics/Viewport.cs | 25 ++++-- OpenRA.Game/Manifest.cs | 6 ++ OpenRA.Game/Map/CellLayer.cs | 12 +-- OpenRA.Game/Map/CellRegion.cs | 15 ++-- OpenRA.Game/Map/Map.cs | 113 +++++++++++++++++++----- OpenRA.Game/Widgets/MapPreviewWidget.cs | 3 +- OpenRA.Mods.RA/Move/PathSearch.cs | 2 +- OpenRA.Mods.RA/Widgets/RadarWidget.cs | 8 +- OpenRA.Utility/LegacyMapImporter.cs | 4 +- 11 files changed, 191 insertions(+), 82 deletions(-) diff --git a/OpenRA.Game/Graphics/Minimap.cs b/OpenRA.Game/Graphics/Minimap.cs index c766273883..f81c6860b4 100644 --- a/OpenRA.Game/Graphics/Minimap.cs +++ b/OpenRA.Game/Graphics/Minimap.cs @@ -20,11 +20,12 @@ namespace OpenRA.Graphics { public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false) { - var width = map.Bounds.Width; - var height = map.Bounds.Height; + var b = map.Bounds; + var width = b.Width; + var height = b.Height; if (!actualSize) - width = height = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); + width = height = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var terrain = new Bitmap(width, height); @@ -37,15 +38,17 @@ namespace OpenRA.Graphics { var c = (int*)bitmapData.Scan0; - for (var x = 0; x < map.Bounds.Width; x++) - for (var y = 0; y < map.Bounds.Height; y++) + for (var x = 0; x < b.Width; x++) + { + for (var y = 0; y < b.Height; y++) { - var mapX = x + map.Bounds.Left; - var mapY = y + map.Bounds.Top; + var mapX = x + b.Left; + var mapY = y + b.Top; var type = tileset.GetTerrainInfo(mapTiles[mapX, mapY]); *(c + (y * bitmapData.Stride >> 2) + x) = type.Color.ToArgb(); } + } } terrain.UnlockBits(bitmapData); @@ -57,6 +60,7 @@ namespace OpenRA.Graphics static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap) { var terrain = new Bitmap(terrainBitmap); + var b = map.Bounds; var bitmapData = terrain.LockBits(terrain.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); @@ -65,11 +69,12 @@ namespace OpenRA.Graphics { var c = (int*)bitmapData.Scan0; - for (var x = 0; x < map.Bounds.Width; x++) - for (var y = 0; y < map.Bounds.Height; y++) + for (var x = 0; x < b.Width; x++) + { + for (var y = 0; y < b.Height; y++) { - var mapX = x + map.Bounds.Left; - var mapY = y + map.Bounds.Top; + var mapX = x + b.Left; + var mapY = y + b.Top; if (map.MapResources.Value[mapX, mapY].Type == 0) continue; @@ -82,6 +87,7 @@ namespace OpenRA.Graphics *(c + (y * bitmapData.Stride >> 2) + x) = tileset[tileset.GetTerrainIndex(res)].Color.ToArgb(); } + } } terrain.UnlockBits(bitmapData); @@ -92,7 +98,9 @@ namespace OpenRA.Graphics public static Bitmap CustomTerrainBitmap(World world) { var map = world.Map; - var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); + var b = map.Bounds; + + var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); @@ -101,16 +109,19 @@ namespace OpenRA.Graphics { var c = (int*)bitmapData.Scan0; - for (var x = 0; x < map.Bounds.Width; x++) - for (var y = 0; y < map.Bounds.Height; y++) + for (var x = 0; x < b.Width; x++) + { + for (var y = 0; y < b.Height; y++) { - var mapX = x + map.Bounds.Left; - var mapY = y + map.Bounds.Top; + var mapX = x + b.Left; + var mapY = y + b.Top; var custom = map.CustomTerrain[mapX, mapY]; if (custom == -1) continue; + *(c + (y * bitmapData.Stride >> 2) + x) = world.TileSet[custom].Color.ToArgb(); } + } } bitmap.UnlockBits(bitmapData); @@ -120,7 +131,9 @@ namespace OpenRA.Graphics public static Bitmap ActorsBitmap(World world) { var map = world.Map; - var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); + var b = map.Bounds; + + var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var bitmap = new Bitmap(size, size); var bitmapData = bitmap.LockBits(bitmap.Bounds(), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); @@ -136,8 +149,11 @@ namespace OpenRA.Graphics var color = t.Trait.RadarSignatureColor(t.Actor); foreach (var cell in t.Trait.RadarSignatureCells(t.Actor)) - if (world.Map.Contains(cell)) - *(c + ((cell.Y - world.Map.Bounds.Top) * bitmapData.Stride >> 2) + cell.X - world.Map.Bounds.Left) = color.ToArgb(); + { + var uv = Map.CellToMap(map.TileShape, cell); + if (b.Contains(uv.X, uv.Y)) + *(c + ((uv.Y - b.Top) * bitmapData.Stride >> 2) + uv.X - b.Left) = color.ToArgb(); + } } } @@ -148,7 +164,9 @@ namespace OpenRA.Graphics public static Bitmap ShroudBitmap(World world) { var map = world.Map; - var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height)); + var b = map.Bounds; + + var size = Exts.NextPowerOf2(Math.Max(b.Width, b.Height)); var bitmap = new Bitmap(size, size); if (world.RenderPlayer == null) return bitmap; @@ -158,20 +176,20 @@ namespace OpenRA.Graphics var shroud = Color.Black.ToArgb(); var fog = Color.FromArgb(128, Color.Black).ToArgb(); + var offset = new CVec(b.Left, b.Top); unsafe { var c = (int*)bitmapData.Scan0; - for (var x = 0; x < map.Bounds.Width; x++) - for (var y = 0; y < map.Bounds.Height; y++) - { - var p = new CPos(x + map.Bounds.Left, y + map.Bounds.Top); - if (world.ShroudObscures(p)) - *(c + (y * bitmapData.Stride >> 2) + x) = shroud; - else if (world.FogObscures(p)) - *(c + (y * bitmapData.Stride >> 2) + x) = fog; - } + foreach (var cell in map.Cells) + { + var uv = Map.CellToMap(map.TileShape, cell) - offset; + if (world.ShroudObscures(cell)) + *(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = shroud; + else if (world.FogObscures(cell)) + *(c + (uv.Y * bitmapData.Stride >> 2) + uv.X) = fog; + } } bitmap.UnlockBits(bitmapData); diff --git a/OpenRA.Game/Graphics/TerrainRenderer.cs b/OpenRA.Game/Graphics/TerrainRenderer.cs index 11dc2f142d..c194be88e3 100644 --- a/OpenRA.Game/Graphics/TerrainRenderer.cs +++ b/OpenRA.Game/Graphics/TerrainRenderer.cs @@ -44,11 +44,12 @@ namespace OpenRA.Graphics { var verticesPerRow = 4*map.Bounds.Width; var cells = viewport.VisibleCells; - var firstRow = cells.TopLeft.Y - map.Bounds.Top; - var lastRow = cells.BottomRight.Y - map.Bounds.Top + 1; + var shape = wr.world.Map.TileShape; - if (lastRow < 0 || firstRow > map.Bounds.Height) - return; + // Only draw the rows that are visible. + // VisibleCells is clamped to the map, so additional checks are unnecessary + var firstRow = Map.CellToMap(shape, cells.TopLeft).Y - map.Bounds.Top; + var lastRow = Map.CellToMap(shape, cells.BottomRight).Y - map.Bounds.Top + 1; Game.Renderer.WorldSpriteRenderer.DrawVertexBuffer( vertexBuffer, verticesPerRow * firstRow, verticesPerRow * (lastRow - firstRow), diff --git a/OpenRA.Game/Graphics/Viewport.cs b/OpenRA.Game/Graphics/Viewport.cs index 3c181f6480..383f6df1d7 100644 --- a/OpenRA.Game/Graphics/Viewport.cs +++ b/OpenRA.Game/Graphics/Viewport.cs @@ -92,8 +92,8 @@ namespace OpenRA.Graphics var b = map.Bounds; // Expand to corners of cells - var tl = wr.ScreenPxPosition(map.CenterOfCell(new CPos(b.Left, b.Top)) - new WVec(512, 512, 0)); - var br = wr.ScreenPxPosition(map.CenterOfCell(new CPos(b.Right, b.Bottom)) + new WVec(511, 511, 0)); + var tl = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Left, b.Top))) - new WVec(512, 512, 0)); + var br = wr.ScreenPxPosition(map.CenterOfCell(Map.MapToCell(map.TileShape, new CPos(b.Right, b.Bottom))) + new WVec(511, 511, 0)); mapBounds = Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y); CenterLocation = (tl + br) / 2; @@ -138,8 +138,13 @@ namespace OpenRA.Graphics { get { - var ctl = worldRenderer.world.Map.CenterOfCell(VisibleCells.TopLeft) - new WVec(512, 512, 0); - var cbr = worldRenderer.world.Map.CenterOfCell(VisibleCells.BottomRight) + new WVec(511, 511, 0); + // Visible rectangle in world coordinates (expanded to the corners of the cells) + // Expand the cordon by an additional cell to account for staggered rows on diamond cell grids. + var map = worldRenderer.world.Map; + var ctl = map.CenterOfCell(VisibleCells.TopLeft) - new WVec(1536, 1536, 0); + var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(1535, 1535, 0); + + // Convert to screen coordinates var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl)).Clamp(ScreenClip); var br = WorldToViewPx(worldRenderer.ScreenPxPosition(cbr)).Clamp(ScreenClip); return Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y); @@ -152,12 +157,16 @@ namespace OpenRA.Graphics { if (cellsDirty) { - // Calculate the intersection of the visible rectangle and the map. + // Visible rectangle in map coordinates var map = worldRenderer.world.Map; - var tl = map.Clamp(map.CellContaining(worldRenderer.Position(TopLeft)) - new CVec(1, 1)); - var br = map.Clamp(map.CellContaining(worldRenderer.Position(BottomRight))); + var ctl = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(TopLeft))); + var cbr = Map.CellToMap(map.TileShape, map.CellContaining(worldRenderer.Position(BottomRight))); - cells = new CellRegion(tl, br); + // Add a 2 cell cordon to prevent holes, then convert back to cell coordinates + var tl = map.Clamp(Map.MapToCell(map.TileShape, ctl - new CVec(2, 2))); + var br = map.Clamp(Map.MapToCell(map.TileShape, cbr + new CVec(2, 2))); + + cells = new CellRegion(map.TileShape, tl, br); cellsDirty = false; } diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 194dadca8c..ece91098dc 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -16,6 +16,8 @@ using OpenRA.Primitives; namespace OpenRA { + public enum TileShape { Rectangle, Diamond } + // Describes what is to be loaded in order to run a mod public class Manifest { @@ -33,6 +35,7 @@ namespace OpenRA public readonly Dictionary> Fonts; public readonly Size TileSize = new Size(24, 24); public readonly string NewsUrl; + public readonly TileShape TileShape = TileShape.Rectangle; public Manifest(string mod) { @@ -77,6 +80,9 @@ namespace OpenRA if (yaml.ContainsKey("TileSize")) TileSize = FieldLoader.GetValue("TileSize", yaml["TileSize"].Value); + if (yaml.ContainsKey("TileShape")) + TileShape = FieldLoader.GetValue("TileShape", yaml["TileShape"].Value); + // Allow inherited mods to import parent maps. var compat = new List(); compat.Add(mod); diff --git a/OpenRA.Game/Map/CellLayer.cs b/OpenRA.Game/Map/CellLayer.cs index 7f973b8902..3c0f444840 100644 --- a/OpenRA.Game/Map/CellLayer.cs +++ b/OpenRA.Game/Map/CellLayer.cs @@ -20,22 +20,24 @@ namespace OpenRA public class CellLayer : IEnumerable { public readonly Size Size; + public readonly TileShape Shape; T[] entries; public CellLayer(Map map) - : this(new Size(map.MapSize.X, map.MapSize.Y)) { } + : this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { } - public CellLayer(Size size) + public CellLayer(TileShape shape, Size size) { Size = size; + Shape = shape; entries = new T[size.Width * size.Height]; } // Resolve an array index from cell coordinates int Index(CPos cell) { - // This will eventually define a distinct case for diagonal cell grids - return cell.Y * Size.Width + cell.X; + var uv = Map.CellToMap(Shape, cell); + return uv.Y * Size.Width + uv.X; } /// Gets or sets the using cell coordinates @@ -90,7 +92,7 @@ namespace OpenRA /// Create a new layer by resizing another layer. New cells are filled with defaultValue. public static CellLayer Resize(CellLayer layer, Size newSize, T defaultValue) { - var result = new CellLayer(newSize); + var result = new CellLayer(layer.Shape, newSize); var width = Math.Min(layer.Size.Width, newSize.Width); var height = Math.Min(layer.Size.Height, newSize.Height); diff --git a/OpenRA.Game/Map/CellRegion.cs b/OpenRA.Game/Map/CellRegion.cs index 3cdccc7fbe..282030b07f 100644 --- a/OpenRA.Game/Map/CellRegion.cs +++ b/OpenRA.Game/Map/CellRegion.cs @@ -23,25 +23,26 @@ namespace OpenRA // Corners of the region public readonly CPos TopLeft; public readonly CPos BottomRight; + readonly TileShape shape; // Corners in map coordinates - // Defined for forward compatibility with diagonal cell grids + // These will only equal TopLeft and BottomRight for TileShape.Rectangular readonly CPos mapTopLeft; readonly CPos mapBottomRight; - public CellRegion(CPos topLeft, CPos bottomRight) + public CellRegion(TileShape shape, CPos topLeft, CPos bottomRight) { + this.shape = shape; TopLeft = topLeft; BottomRight = bottomRight; - mapTopLeft = TopLeft; - mapBottomRight = BottomRight; + mapTopLeft = Map.CellToMap(shape, TopLeft); + mapBottomRight = Map.CellToMap(shape, BottomRight); } public bool Contains(CPos cell) { - // Defined for forward compatibility with diagonal cell grids - var uv = cell; + var uv = Map.CellToMap(shape, cell); return uv.X >= mapTopLeft.X && uv.X <= mapBottomRight.X && uv.Y >= mapTopLeft.Y && uv.Y <= mapBottomRight.Y; } @@ -93,7 +94,7 @@ namespace OpenRA v = r.mapTopLeft.Y; } - public CPos Current { get { return new CPos(u, v); } } + public CPos Current { get { return Map.MapToCell(r.shape, new CPos(u, v)); } } object IEnumerator.Current { get { return Current; } } public void Dispose() { } } diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 8cbe791316..484362f138 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -76,6 +76,8 @@ namespace OpenRA public bool AllowStartUnitConfig = true; public Bitmap CustomPreview; + public readonly TileShape TileShape; + [FieldLoader.LoadUsing("LoadOptions")] public MapOptions Options; @@ -125,11 +127,12 @@ namespace OpenRA public static Map FromTileset(TileSet tileset) { var size = new Size(1, 1); + var tileShape = Game.modData.Manifest.TileShape; var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0); var makeMapTiles = Exts.Lazy(() => { - var ret = new CellLayer(size); + var ret = new CellLayer(tileShape, size); ret.Clear(tileRef); return ret; }); @@ -142,7 +145,7 @@ namespace OpenRA MapSize = new int2(size), Tileset = tileset.Id, Options = new MapOptions(), - MapResources = Exts.Lazy(() => new CellLayer(size)), + MapResources = Exts.Lazy(() => new CellLayer(tileShape, size)), MapTiles = makeMapTiles, Actors = Exts.Lazy(() => new Dictionary()), Smudges = Exts.Lazy(() => new List()) @@ -242,6 +245,7 @@ namespace OpenRA MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); + TileShape = Game.modData.Manifest.TileShape; // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. @@ -262,9 +266,9 @@ namespace OpenRA rules = Exts.Lazy(() => Game.modData.RulesetCache.LoadMapRules(this)); cachedTileSet = Exts.Lazy(() => Rules.TileSets[Tileset]); - var tl = new CPos(Bounds.Left, Bounds.Top); - var br = new CPos(Bounds.Right - 1, Bounds.Bottom - 1); - Cells = new CellRegion(tl, br); + var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top)); + var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1)); + Cells = new CellRegion(TileShape, tl, br); CustomTerrain = new CellLayer(this); foreach (var cell in Cells) @@ -465,17 +469,79 @@ namespace OpenRA public bool Contains(CPos cell) { - return Bounds.Contains(cell.X, cell.Y); + var uv = CellToMap(TileShape, cell); + return Bounds.Contains(uv.X, uv.Y); } - public WPos CenterOfCell(CPos c) + public WPos CenterOfCell(CPos cell) { - return new WPos(1024 * c.X + 512, 1024 * c.Y + 512, 0); + if (TileShape == TileShape.Rectangle) + return new WPos(1024 * cell.X + 512, 1024 * cell.Y + 512, 0); + + // Convert from diamond cell position (x, y) to world position (u, v): + // (a) Consider the relationships: + // - Center of origin cell is (512, 512) + // - +x adds (512, 512) to world pos + // - +y adds (-512, 512) to world pos + // (b) Therefore: + // - ax + by adds (a - b) * 512 + 512 to u + // - ax + by adds (a + b) * 512 + 512 to v + return new WPos(512 * (cell.X - cell.Y + 1), 512 * (cell.X + cell.Y + 1), 0); } public CPos CellContaining(WPos pos) { - return new CPos(pos.X / 1024, pos.Y / 1024); + if (TileShape == TileShape.Rectangle) + return new CPos(pos.X / 1024, pos.Y / 1024); + + // Convert from world position to diamond cell position: + // (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell + // (b) Rotate axes by -pi/4 + // (c) Add 512 to x (but not y) to realign the cell + // (d) Divide by 1024 to find final cell coords + var u = (pos.Y + pos.X - 512) / 1024; + var v = (pos.Y - pos.X) / 1024; + return new CPos(u, v); + } + + public static CPos MapToCell(TileShape shape, CPos map) + { + if (shape == TileShape.Rectangle) + return map; + + // Convert from rectangular map position to diamond cell position + // - The staggered rows make this fiddly (hint: draw a diagram!) + // (a) Consider the relationships: + // - +1u (even -> odd) adds (1, -1) to (x, y) + // - +1v (even -> odd) adds (1, 0) to (x, y) + // - +1v (odd -> even) adds (0, 1) to (x, y) + // (b) Therefore: + // - au + 2bv adds (a + b) to (x, y) + // - a correction factor is added if v is odd + var offset = (map.Y & 1) == 1 ? 1 : 0; + var y = (map.Y - offset) / 2 - map.X; + var x = map.Y - y; + return new CPos(x, y); + } + + public static CPos CellToMap(TileShape shape, CPos cell) + { + if (shape == TileShape.Rectangle) + return cell; + + // Convert from diamond cell (x, y) position to rectangular map position (u, v) + // - The staggered rows make this fiddly (hint: draw a diagram!) + // (a) Consider the relationships: + // - +1x (even -> odd) adds (0, 1) to (u, v) + // - +1x (odd -> even) adds (1, 1) to (u, v) + // - +1y (even -> odd) adds (-1, 1) to (u, v) + // - +1y (odd -> even) adds (0, 1) to (u, v) + // (b) Therefore: + // - ax + by adds (a - b)/2 to u (only even increments count) + // - ax + by adds a + b to v + var u = (cell.X - cell.Y) / 2; + var v = cell.X + cell.Y; + return new CPos(u, v); } public int FacingBetween(CPos cell, CPos towards, int fallbackfacing) @@ -497,7 +563,10 @@ namespace OpenRA public void ResizeCordon(int left, int top, int right, int bottom) { Bounds = Rectangle.FromLTRB(left, top, right, bottom); - Cells = new CellRegion(new CPos(Bounds.Left, Bounds.Top), new CPos(Bounds.Right - 1, Bounds.Bottom - 1)); + + var tl = Map.MapToCell(TileShape, new CPos(Bounds.Left, Bounds.Top)); + var br = Map.MapToCell(TileShape, new CPos(Bounds.Right - 1, Bounds.Bottom - 1)); + Cells = new CellRegion(TileShape, tl, br); } string ComputeHash() @@ -597,17 +666,18 @@ namespace OpenRA return cachedTileSet.Value[GetTerrainIndex(cell)]; } - public CPos Clamp(CPos xy) + public CPos Clamp(CPos cell) { - var r = Bounds; - return xy.Clamp(new Rectangle(r.X, r.Y, r.Width - 1, r.Height - 1)); + var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1); + return MapToCell(TileShape, CellToMap(TileShape, cell).Clamp(bounds)); } public CPos ChooseRandomCell(MersenneTwister rand) { - return new CPos( - rand.Next(Bounds.Left, Bounds.Right), - rand.Next(Bounds.Top, Bounds.Bottom)); + var x = rand.Next(Bounds.Left, Bounds.Right); + var y = rand.Next(Bounds.Top, Bounds.Bottom); + + return MapToCell(TileShape, new CPos(x, y)); } public CPos ChooseRandomEdgeCell(MersenneTwister rand) @@ -615,15 +685,16 @@ namespace OpenRA var isX = rand.Next(2) == 0; var edge = rand.Next(2) == 0; - return new CPos( - isX ? rand.Next(Bounds.Left, Bounds.Right) : (edge ? Bounds.Left : Bounds.Right), - !isX ? rand.Next(Bounds.Top, Bounds.Bottom) : (edge ? Bounds.Top : Bounds.Bottom)); + var x = isX ? rand.Next(Bounds.Left, Bounds.Right) : (edge ? Bounds.Left : Bounds.Right); + var y = !isX ? rand.Next(Bounds.Top, Bounds.Bottom) : (edge ? Bounds.Top : Bounds.Bottom); + + return MapToCell(TileShape, new CPos(x, y)); } public WRange DistanceToEdge(WPos pos, WVec dir) { - var tl = CenterOfCell(new CPos(Bounds.Left, Bounds.Top)) - new WVec(512, 512, 0); - var br = CenterOfCell(new CPos(Bounds.Right, Bounds.Bottom)) + new WVec(511, 511, 0); + var tl = CenterOfCell(Cells.TopLeft) - new WVec(512, 512, 0); + var br = CenterOfCell(Cells.BottomRight) + new WVec(511, 511, 0); var x = dir.X == 0 ? int.MaxValue : ((dir.X < 0 ? tl.X : br.X) - pos.X) / dir.X; var y = dir.Y == 0 ? int.MaxValue : ((dir.Y < 0 ? tl.Y : br.Y) - pos.Y) / dir.Y; return new WRange(Math.Min(x, y) * dir.Length); diff --git a/OpenRA.Game/Widgets/MapPreviewWidget.cs b/OpenRA.Game/Widgets/MapPreviewWidget.cs index 384bd8b316..c70aab3c0f 100644 --- a/OpenRA.Game/Widgets/MapPreviewWidget.cs +++ b/OpenRA.Game/Widgets/MapPreviewWidget.cs @@ -129,9 +129,10 @@ namespace OpenRA.Widgets tooltipContainer.Value.RemoveTooltip(); } - public int2 ConvertToPreview(CPos point) + public int2 ConvertToPreview(CPos cell) { var preview = Preview(); + var point = Map.CellToMap(preview.Map.TileShape, cell); var dx = (int)(previewScale * (point.X - preview.Bounds.Left)); var dy = (int)(previewScale * (point.Y - preview.Bounds.Top)); return new int2(mapRect.X + dx, mapRect.Y + dy); diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs index 1b61a86814..93a3ccb2fb 100755 --- a/OpenRA.Mods.RA/Move/PathSearch.cs +++ b/OpenRA.Mods.RA/Move/PathSearch.cs @@ -287,7 +287,7 @@ namespace OpenRA.Mods.RA.Move while (CellInfoPool.Count > 0) { var cellInfo = GetFromPool(); - if (cellInfo.Size != mapSize) + if (cellInfo.Size != mapSize || cellInfo.Shape != self.World.Map.TileShape) { Log.Write("debug", "Discarding old pooled CellInfo of wrong size."); continue; diff --git a/OpenRA.Mods.RA/Widgets/RadarWidget.cs b/OpenRA.Mods.RA/Widgets/RadarWidget.cs index 960e484b5e..e7b4fdaa96 100755 --- a/OpenRA.Mods.RA/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.RA/Widgets/RadarWidget.cs @@ -115,7 +115,7 @@ namespace OpenRA.Mods.RA.Widgets var cell = MinimapPixelToCell(mi.Location); var pos = world.Map.CenterOfCell(cell); if ((mi.Event == MouseInputEvent.Down || mi.Event == MouseInputEvent.Move) && mi.Button == MouseButton.Left) - worldRenderer.Viewport.Center(world.Map.CenterOfCell(cell)); + worldRenderer.Viewport.Center(pos); if (mi.Event == MouseInputEvent.Down && mi.Button == MouseButton.Right) { @@ -242,8 +242,8 @@ namespace OpenRA.Mods.RA.Widgets int2 CellToMinimapPixel(CPos p) { - var mapOrigin = new CPos(world.Map.Bounds.Left, world.Map.Bounds.Top); - var mapOffset = p - mapOrigin; + var mapOrigin = new CVec(world.Map.Bounds.Left, world.Map.Bounds.Top); + var mapOffset = Map.CellToMap(world.Map.TileShape, p) - mapOrigin; return new int2(mapRect.X, mapRect.Y) + (previewScale * new float2(mapOffset.X, mapOffset.Y)).ToInt2(); } @@ -253,7 +253,7 @@ namespace OpenRA.Mods.RA.Widgets var viewOrigin = new float2(mapRect.X, mapRect.Y); var mapOrigin = new float2(world.Map.Bounds.Left, world.Map.Bounds.Top); var fcell = mapOrigin + (1f / previewScale) * (p - viewOrigin); - return new CPos((int)fcell.X, (int)fcell.Y); + return Map.MapToCell(world.Map.TileShape, new CPos((int)fcell.X, (int)fcell.Y)); } } } diff --git a/OpenRA.Utility/LegacyMapImporter.cs b/OpenRA.Utility/LegacyMapImporter.cs index ded0b9d2ab..ce83937535 100644 --- a/OpenRA.Utility/LegacyMapImporter.cs +++ b/OpenRA.Utility/LegacyMapImporter.cs @@ -149,8 +149,8 @@ namespace OpenRA.Utility map.Smudges = Exts.Lazy(() => new List()); map.Actors = Exts.Lazy(() => new Dictionary()); - map.MapResources = Exts.Lazy(() => new CellLayer(size)); - map.MapTiles = Exts.Lazy(() => new CellLayer(size)); + map.MapResources = Exts.Lazy(() => new CellLayer(TileShape.Rectangle, size)); + map.MapTiles = Exts.Lazy(() => new CellLayer(TileShape.Rectangle, size)); map.Options = new MapOptions(); From 68969203bbaf5ae00bfe89984b102a91c804ad3a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 30 Jun 2014 11:30:20 +1200 Subject: [PATCH 3/6] Extract TS blank-conquest map. --- mods/ts/maps/blank-conquest.oramap | Bin 1309 -> 0 bytes mods/ts/maps/blank-conquest/map.bin | Bin 0 -> 81925 bytes mods/ts/maps/blank-conquest/map.yaml | 85 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) delete mode 100644 mods/ts/maps/blank-conquest.oramap create mode 100644 mods/ts/maps/blank-conquest/map.bin create mode 100644 mods/ts/maps/blank-conquest/map.yaml diff --git a/mods/ts/maps/blank-conquest.oramap b/mods/ts/maps/blank-conquest.oramap deleted file mode 100644 index 512fdbb8fb21182eb94d4f13d928dae1e73412ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1309 zcmWIWW@Zs#U|`^2Fq$yMW&Zh}=1Z6u7+4(`8Q6iMxrqgONttPe&YS~*31TNbjownhZ{rdNxRy|(0)k$7@{idVOWw!i!`%|y_ z%YVtebw|>>Mw;~zQx{FIet*?x_4ir@w@q3ZQEAc zKdZS?@7C)b%l;}SKiT%ZPHotnQZt*^M`jo+tUH&}ZJq8o_q+F*#z~Lsv-kJ!{JnR5 z+{NGC^1{U{|L!~fJ^>{^g{g=|%-^=DOX0I&%cjD{67uAWknP1PaU|&=J+IF|g z)Z!~uu7A(pHB)-_$<*rE$6x<#xw8Ix=XdXX-?9FW&F{xnuWqVm=~-Tn-h2GFOTqQc ziSwA^-uf8C{H^}>^JdvL3C2>@igPSqS*EQ0ywPr&V)%jdZnSMC4^M2jz`Jwq2F8iOH{O+3nj#`~B>IZj8y*WQa{>z{GZ|Q%v zqaM9^T`$Y&-S^vg-|~g8Zj~|?~{u=qUU=^ zA2^YJ;M~78m+uwJ1irnORvov#Fn?~F-}-Ns-|PPs)vleye0~3u$o+4bzdw(DANSv` zcJhG?lo{-L;SW75^jm)5XynVd|herue)xi=uP z=xg&jTmSq`-M!l;sd~)*rrN+VQDlF=h-=uA6(1{>d#G&XWidGZ@6rvvy&isyUR7L| zCe5B5rgD$*$|e4N&$+%TAMh{gow|3rTlbUchuXs2wx%#HJGj0_^rXz*c+V0YkFVc- z`=@UWdD5XAqx-7+Q&wbOqV~^IXCnXEKIJXQYs!RQ%&oy_~ zZd?_6y~Va?-pqG=wpsu0M|>)F{dD2f_a~nh?3t6ZbMd)X4|W8<<@M~`Wh%Q`e3q5x zpI0+gU)^PVmeX%(Emgel_#FA(oi~#8`VPvxjegd9f4cm(rG4>}k69g4_P;K9Xv@d6 zH}e8#bS!xt+kbu*=Q`i!jqg7zo$bD1mQwyJ<4B5p@}`sN3;rZukn}&MV$Gt(m-4;W z@n^L_NNk3DhQuVJ6(84B+-Tp#_o?@%bJq0&?;FQw?lLr*C3fs|wInldRc@g5*1-Ra y0p5&E#tgViC)BbAT2`TJLQe?@O(%f`9Y_->T?BZuvVmlnfG`_K&jF?z1_l5e&rsI@ diff --git a/mods/ts/maps/blank-conquest/map.bin b/mods/ts/maps/blank-conquest/map.bin new file mode 100644 index 0000000000000000000000000000000000000000..1538bf20970c4a5f8ba9e97f9c9291c998823e63 GIT binary patch literal 81925 zcmeI%%aYSD5CzaElQ^%R=Fj1FTMn6G!ICO*971f*u((I9mK?^9(~r~7lRpFq5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAVA>X z3!EGT2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly z@D>>7aUaide&6Vm+&PWw_j@Z|CHrm9HNM6;oyIG#OH3{ixX0iRnY9!W`F$k$7J*bk zDb(#aY~z~OzYx|JNe7tG)6fr6?}&2ioYcJGubo78SPh@ zbRFDs{+07{ezxTukJXNv^BMC;GJaJbsM)^Pdf!R<+tn71YxaQO>s}H+yWXoN&YAVE^n`QX-6C^!Uu)zu;x*Kk9tF@vlTZ`jx+WeOYwQRK?b>4xOvZ zYUwL^9mzcMzRkRImM3v$eD2mRVCz}2-1?VvHRg|fWlIHAC&+Fm_iFc>tI}ztI@|V6 zcwDdW*|mSH_&xXMzW3g{q1q8uU##O=U1EjI-!sf?wF|0QP(ARGtXq$Lt%I}cExP*| zz0=L}O%m4{*R_z5t~pTsZ?67z_1$fatGU;$Q6F9L)&Hv!vI^w$k@^8H(&JQ=KeBxQB`SMt{? zaF0axf|a+=FS)ni-uH7nXWC=m|M8=J*4Hj^<)bUUzU!@Zpuhh*($4(z8{*^cx}Wt# z@VU$FRq)%Lb+hlu()rT+=J`lP%pSOU?$3N#2kLn^d*AfL|KR_CKC?R~K!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 H{wDAXK=aOp literal 0 HcmV?d00001 diff --git a/mods/ts/maps/blank-conquest/map.yaml b/mods/ts/maps/blank-conquest/map.yaml new file mode 100644 index 0000000000..fa4e9bc77e --- /dev/null +++ b/mods/ts/maps/blank-conquest/map.yaml @@ -0,0 +1,85 @@ +Selectable: True + +MapFormat: 6 + +RequiresMod: ts + +Title: Blank + +Description: Placeholder + +Author: Matthias Mailänder + +Tileset: INTERIOR + +MapSize: 128,128 + +Bounds: 16,16,96,96 + +UseAsShellmap: False + +Type: Conquest + +Options: + +Players: + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Race: gdi + PlayerReference@Multi0: + Name: Multi0 + Playable: True + Race: Random + Enemies: Creeps + PlayerReference@Multi1: + Name: Multi1 + Playable: True + Race: Random + Enemies: Creeps + PlayerReference@Multi2: + Name: Multi2 + Playable: True + Race: Random + Enemies: Creeps + PlayerReference@Multi3: + Name: Multi3 + Playable: True + Race: Random + Enemies: Creeps + PlayerReference@Creeps: + Name: Creeps + NonCombatant: True + Race: gdi + Enemies: Multi0,Multi1,Multi2,Multi3 + +Actors: + Actor0: mpspawn + Location: 23,23 + Owner: Neutral + Actor1: mpspawn + Location: 103,23 + Owner: Neutral + Actor2: mpspawn + Location: 98,101 + Owner: Neutral + Actor3: mpspawn + Location: 25,102 + Owner: Neutral + +Smudges: + +Rules: + +Sequences: + +VoxelSequences: + +Weapons: + +Voices: + +Notifications: + +Translations: From 0866903f2048887e9604ca2f2f3213dfe0d217b9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 30 Jun 2014 12:10:49 +1200 Subject: [PATCH 4/6] remove blank-testmap. --- mods/ts/maps/blank-testmap/map.bin | Bin 81925 -> 0 bytes mods/ts/maps/blank-testmap/map.yaml | 121 ---------------------------- 2 files changed, 121 deletions(-) delete mode 100644 mods/ts/maps/blank-testmap/map.bin delete mode 100644 mods/ts/maps/blank-testmap/map.yaml diff --git a/mods/ts/maps/blank-testmap/map.bin b/mods/ts/maps/blank-testmap/map.bin deleted file mode 100644 index 011a9c1426040f7a2d9b2f953b469dd3d74e5771..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81925 zcmeIuK@k8j2*9x79Os)1KIv6KX4_sSK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk_X3Fk0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ VfB*pk1PBlyK!5-N0t5&U=mR8^#IpbZ diff --git a/mods/ts/maps/blank-testmap/map.yaml b/mods/ts/maps/blank-testmap/map.yaml deleted file mode 100644 index 3cfb223bb1..0000000000 --- a/mods/ts/maps/blank-testmap/map.yaml +++ /dev/null @@ -1,121 +0,0 @@ -Selectable: True - -MapFormat: 6 - -RequiresMod: ts - -Title: Blank Test Map - -Description: Test Map - -Author: Reaperrr - -Tileset: INTERIOR - -MapSize: 128,128 - -Bounds: 16,16,96,96 - -UseAsShellmap: False - -Type: Conquest - -Options: - -Players: - PlayerReference@Neutral: - Name: Neutral - OwnsWorld: True - NonCombatant: True - Race: gdi - PlayerReference@Multi0: - Name: Multi0 - Playable: True - Race: Random - Enemies: Creeps - PlayerReference@Multi1: - Name: Multi1 - Playable: True - Race: Random - Enemies: Creeps - PlayerReference@Multi2: - Name: Multi2 - Playable: True - Race: Random - Enemies: Creeps - PlayerReference@Multi3: - Name: Multi3 - Playable: True - Race: Random - Enemies: Creeps - PlayerReference@Creeps: - Name: Creeps - NonCombatant: True - Race: gdi - Enemies: Multi0,Multi1,Multi2,Multi3 - -Actors: - Actor0: mpspawn - Location: 23,23 - Owner: Neutral - Actor1: mpspawn - Location: 103,23 - Owner: Neutral - Actor2: gatech - Location: 90,80 - Owner: Creeps - Actor3: natech - Location: 86,80 - Owner: Creeps - Actor4: naradr - Location: 82,80 - Owner: Creeps - Actor5: hvr - Location: 40,80 - Owner: Creeps - Actor6: cyborg - Location: 38,80 - Owner: Creeps - Actor7: cyc2 - Location: 36,80 - Owner: Creeps - Actor8: bike - Location: 34,80 - Owner: Creeps - Actor9: ttnk - Location: 32,80 - Owner: Creeps - Actor10: mmch - Location: 30,80 - Owner: Creeps - Actor11: gapowr - Location: 90,85 - Owner: Creeps - Actor12: gapowr - Location: 87,85 - Owner: Creeps - Actor13: napowr - Location: 84,85 - Owner: Creeps - Actor14: napowr - Location: 81,85 - Owner: Creeps - Actor15: napowr - Location: 78,85 - Owner: Creeps - -Smudges: - -Rules: - -Sequences: - -VoxelSequences: - -Weapons: - -Voices: - -Notifications: - -Translations: From 96c9de2b9603abee1977b2ea20f5081968aa7fb3 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 30 Jun 2014 11:26:18 +1200 Subject: [PATCH 5/6] Enable isometric perspective in TS. --- mods/ts/maps/blank-conquest/map.yaml | 10 +++---- mods/ts/mod.yaml | 1 + mods/ts/sequences/misc.yaml | 40 ++++++++++++++-------------- mods/ts/tilesets/interior.yaml | 2 +- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/mods/ts/maps/blank-conquest/map.yaml b/mods/ts/maps/blank-conquest/map.yaml index fa4e9bc77e..1f575b9014 100644 --- a/mods/ts/maps/blank-conquest/map.yaml +++ b/mods/ts/maps/blank-conquest/map.yaml @@ -14,7 +14,7 @@ Tileset: INTERIOR MapSize: 128,128 -Bounds: 16,16,96,96 +Bounds: 32,16,48,96 UseAsShellmap: False @@ -56,16 +56,16 @@ Players: Actors: Actor0: mpspawn - Location: 23,23 + Location: 50,-24 Owner: Neutral Actor1: mpspawn - Location: 103,23 + Location: 126,-24 Owner: Neutral Actor2: mpspawn - Location: 98,101 + Location: 88,14 Owner: Neutral Actor3: mpspawn - Location: 25,102 + Location: 88,-62 Owner: Neutral Smudges: diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index b9a38c0848..6b9e1eb993 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -142,6 +142,7 @@ TileSets: mods/ts/tilesets/interior.yaml TileSize: 48,24 +TileShape: Diamond Music: mods/ts/music.yaml diff --git a/mods/ts/sequences/misc.yaml b/mods/ts/sequences/misc.yaml index 45cf0b5c68..5cf2c51d14 100644 --- a/mods/ts/sequences/misc.yaml +++ b/mods/ts/sequences/misc.yaml @@ -1,24 +1,24 @@ overlay: - build-valid-interior: cellsel #TODO remove backfall to RA tileset - Start: 3 - build-valid-snow: cellsel - Start: 3 - build-valid-temperat: cellsel - Start: 3 - build-invalid: cellsel - Start: 6 - target-select: cellsel - Start: 10 - target-valid-desert: cellsel - Start: 3 - target-valid-interior: cellsel - Start: 3 - target-valid-snow: cellsel - Start: 3 - target-valid-temperat: cellsel - Start: 3 - target-invalid: cellsel - Start: 6 + build-valid-interior: place + Start: 0 + build-valid-snow: place + Start: 0 + build-valid-temperat: place + Start: 0 + build-invalid: place + Start: 1 + target-select: place + Start: 1 + target-valid-desert: place + Start: 1 + target-valid-interior: place + Start: 1 + target-valid-snow: place + Start: 1 + target-valid-temperat: place + Start: 1 + target-invalid: place + Start: 1 poweroff: offline: poweroff diff --git a/mods/ts/tilesets/interior.yaml b/mods/ts/tilesets/interior.yaml index a6ec53d092..f98b79d3ee 100644 --- a/mods/ts/tilesets/interior.yaml +++ b/mods/ts/tilesets/interior.yaml @@ -9,7 +9,7 @@ Terrain: TerrainType@Clear: Type: Clear AcceptsSmudgeType: Crater, Scorch - Color: 0, 0, 0 + Color: 116, 85, 55 TargetTypes: Ground TerrainType@Tiberium: Type: Tiberium From 0d625b6af6178768d13cdc11178c9515419662fc Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Tue, 1 Jul 2014 00:24:26 +1200 Subject: [PATCH 6/6] Fix sprite overlap outside the map border. --- OpenRA.Game/Graphics/Viewport.cs | 5 ++--- OpenRA.Game/Map/CellRegion.cs | 10 ++++++++++ OpenRA.Mods.RA/ShroudRenderer.cs | 12 ++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/OpenRA.Game/Graphics/Viewport.cs b/OpenRA.Game/Graphics/Viewport.cs index 383f6df1d7..83970ec606 100644 --- a/OpenRA.Game/Graphics/Viewport.cs +++ b/OpenRA.Game/Graphics/Viewport.cs @@ -139,10 +139,9 @@ namespace OpenRA.Graphics get { // Visible rectangle in world coordinates (expanded to the corners of the cells) - // Expand the cordon by an additional cell to account for staggered rows on diamond cell grids. var map = worldRenderer.world.Map; - var ctl = map.CenterOfCell(VisibleCells.TopLeft) - new WVec(1536, 1536, 0); - var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(1535, 1535, 0); + var ctl = map.CenterOfCell(VisibleCells.TopLeft) - new WVec(512, 512, 0); + var cbr = map.CenterOfCell(VisibleCells.BottomRight) + new WVec(512, 512, 0); // Convert to screen coordinates var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl)).Clamp(ScreenClip); diff --git a/OpenRA.Game/Map/CellRegion.cs b/OpenRA.Game/Map/CellRegion.cs index 282030b07f..ce7316ecd1 100644 --- a/OpenRA.Game/Map/CellRegion.cs +++ b/OpenRA.Game/Map/CellRegion.cs @@ -40,6 +40,16 @@ namespace OpenRA mapBottomRight = Map.CellToMap(shape, BottomRight); } + /// Expand the specified region with an additional cordon. This may expand the region outside the map borders. + public static CellRegion Expand(CellRegion region, int cordon) + { + var offset = new CVec(cordon, cordon); + var tl = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.TopLeft) - offset); + var br = Map.MapToCell(region.shape, Map.CellToMap(region.shape, region.BottomRight) + offset); + + return new CellRegion(region.shape, tl, br); + } + public bool Contains(CPos cell) { var uv = Map.CellToMap(shape, cell); diff --git a/OpenRA.Mods.RA/ShroudRenderer.cs b/OpenRA.Mods.RA/ShroudRenderer.cs index 0d5b45ff12..10a44b1fc5 100644 --- a/OpenRA.Mods.RA/ShroudRenderer.cs +++ b/OpenRA.Mods.RA/ShroudRenderer.cs @@ -197,11 +197,19 @@ namespace OpenRA.Mods.RA public void WorldLoaded(World w, WorldRenderer wr) { // Initialize tile cache - foreach (var cell in map.Cells) + // Adds a 1-cell border around the border to cover any sprites peeking outside the map + foreach (var cell in CellRegion.Expand(w.Map.Cells, 1)) { var screen = wr.ScreenPosition(w.Map.CenterOfCell(cell)); var variant = Game.CosmeticRandom.Next(info.ShroudVariants.Length); tiles[cell] = new ShroudTile(cell, screen, variant); + + // Set the cells outside the border so they don't need to be touched again + if (!map.Contains(cell)) + { + var index = info.UseExtendedIndex ? 240 : 15; + tiles[cell].Shroud = shroudSprites[variant * variantStride + spriteMap[index]]; + } } fogPalette = wr.Palette(info.FogPalette); @@ -253,7 +261,7 @@ namespace OpenRA.Mods.RA { Update(shroud); - foreach (var cell in wr.Viewport.VisibleCells) + foreach (var cell in CellRegion.Expand(wr.Viewport.VisibleCells, 1)) { var t = tiles[cell];