diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs index 945e600e0e..61d0fe44bf 100644 --- a/OpenRa.Game/Chrome.cs +++ b/OpenRa.Game/Chrome.cs @@ -346,10 +346,8 @@ namespace OpenRa } bool PaletteAvailable(int index) { return Game.LobbyInfo.Clients.All(c => c.PaletteIndex != index); } - bool SpawnPointAvailable(int index) { return Game.LobbyInfo.Clients.All(c => c.SpawnPoint != index); } - void CyclePalette(bool left) { var d = left ? +1 : Player.PlayerColors.Count() - 1; @@ -379,14 +377,13 @@ namespace OpenRa void CycleSpawnPoint(bool left) { - var d = left ? +1 : Game.world.Map.SpawnPoints.Count() - 1; + var d = left ? +1 : Game.world.Map.SpawnPoints.Count(); - var newIndex = (Game.world.LocalPlayer.SpawnPointIndex + d) % Game.world.Map.SpawnPoints.Count(); + var newIndex = (Game.world.LocalPlayer.SpawnPointIndex + d) % (Game.world.Map.SpawnPoints.Count()+1); while (!SpawnPointAvailable(newIndex) && newIndex != (int)Game.world.LocalPlayer.SpawnPointIndex) - newIndex = (newIndex + d) % Game.world.Map.SpawnPoints.Count(); + newIndex = (newIndex + d) % (Game.world.Map.SpawnPoints.Count()+1); - Game.world.Minimap.InvalidateSpawnPoints(); Game.IssueOrder( Order.Chat("/spawn " + newIndex)); @@ -413,6 +410,7 @@ namespace OpenRa var minimapRect = new Rectangle(r.Right - 322, r.Top + 45, 300, 240); world.Minimap.Update(); + world.Minimap.Draw(minimapRect, true); world.Minimap.DrawSpawnPoints(minimapRect); if (Game.world.LocalPlayer.Index == 0) diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index a6cf1fa3e9..003936aded 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -70,7 +70,10 @@ namespace OpenRa Timer.Time( "load rules: {0}" ); world = null; // trying to access the old world will NRE, rather than silently doing it wrong. + Player.ResetPlayerColorList(); + ChromeProvider.Initialize(manifest.Chrome); + world = new World(); Game.world.ActorAdded += a => @@ -80,7 +83,6 @@ namespace OpenRa }; Timer.Time( "world: {0}" ); - ChromeProvider.Initialize(manifest.Chrome); SequenceProvider.Initialize(manifest.Sequences); viewport = new Viewport(clientSize, Game.world.Map.Offset, Game.world.Map.Offset + Game.world.Map.Size, renderer); Timer.Time( "ChromeProv, SeqProv, viewport: {0}" ); diff --git a/OpenRa.Game/Graphics/Minimap.cs b/OpenRa.Game/Graphics/Minimap.cs index 4bcaac4407..a2f3cbe934 100644 --- a/OpenRa.Game/Graphics/Minimap.cs +++ b/OpenRa.Game/Graphics/Minimap.cs @@ -6,6 +6,7 @@ using OpenRa.FileFormats; using System.Drawing.Imaging; using IjwFramework.Collections; using System.Collections.Generic; +using IjwFramework.Types; namespace OpenRa.Graphics { @@ -14,8 +15,14 @@ namespace OpenRa.Graphics readonly World world; Sheet sheet, mapOnlySheet, mapSpawnPointSheet; SpriteRenderer rgbaRenderer; + LineRenderer lineRenderer; Sprite sprite, mapOnlySprite, mapSpawnPointSprite; Bitmap terrain, oreLayer, spawnPointsLayer; + Rectangle bounds; + + Sprite ownedSpawnPoint; + Sprite unownedSpawnPoint; + const int alpha = 230; public void Tick() { } @@ -27,18 +34,22 @@ namespace OpenRa.Graphics mapOnlySheet = new Sheet(r, new Size(128, 128)); mapSpawnPointSheet = new Sheet(r, new Size(128, 128)); + lineRenderer = new LineRenderer(r); rgbaRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader); var size = Math.Max(world.Map.Width, world.Map.Height); var dw = (size - world.Map.Width) / 2; var dh = (size - world.Map.Height) / 2; - var rect = new Rectangle(world.Map.Offset.X - dw, world.Map.Offset.Y - dh, size, size); + bounds = new Rectangle(world.Map.Offset.X - dw, world.Map.Offset.Y - dh, size, size); - sprite = new Sprite(sheet, rect, TextureChannel.Alpha); - mapOnlySprite = new Sprite(mapOnlySheet, rect, TextureChannel.Alpha); - mapSpawnPointSprite = new Sprite(mapSpawnPointSheet, rect, TextureChannel.Alpha); + sprite = new Sprite(sheet, bounds, TextureChannel.Alpha); + mapOnlySprite = new Sprite(mapOnlySheet, bounds, TextureChannel.Alpha); + mapSpawnPointSprite = new Sprite(mapSpawnPointSheet, bounds, TextureChannel.Alpha); shroudColor = Color.FromArgb(alpha, Color.Black); + + ownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "owned"); + unownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "unowned"); } public static Rectangle MakeMinimapBounds(Map m) @@ -79,6 +90,8 @@ namespace OpenRa.Graphics public static Bitmap RenderTerrainBitmapWithSpawnPoints(Map map, TileSet tileset) { + /* todo: do this a bit nicer */ + var terrain = RenderTerrainBitmap(map, tileset); foreach (var sp in map.SpawnPoints) terrain.SetPixel(sp.X, sp.Y, Color.White); @@ -102,27 +115,6 @@ namespace OpenRa.Graphics } mapOnlySheet.Texture.SetData(oreLayer); - mapSpawnPointSheet.Texture.SetData(oreLayer); - - if (spawnPointsLayer == null) - { - spawnPointsLayer = new Bitmap(terrain); - var available = Game.world.Map.SpawnPoints.ToList(); - - foreach (var player in Game.world.players.Values) - { - if (player.SpawnPointIndex != 0) - { - int2 sp = Game.world.Map.SpawnPoints.ElementAt(player.SpawnPointIndex - 1); - spawnPointsLayer.SetPixel(sp.X, sp.Y, player.Color); - available.Remove(sp); - } - } - foreach (var sp in available) - spawnPointsLayer.SetPixel(sp.X, sp.Y, Color.White); - } - - mapSpawnPointSheet.Texture.SetData(spawnPointsLayer); if (!world.Queries.OwnedBy[world.LocalPlayer].WithTrait().Any()) return; @@ -166,10 +158,41 @@ namespace OpenRa.Graphics rgbaRenderer.Flush(); } + int2 TransformCellToMinimapPixel(RectangleF viewRect, int2 p) + { + var fx = (float)(p.X - bounds.X) / bounds.Width; + var fy = (float)(p.Y - bounds.Y) / bounds.Height; + + return new int2( + (int)(viewRect.Width * fx + viewRect.Left) - 8, + (int)(viewRect.Height * fy + viewRect.Top) - 8); + } + public void DrawSpawnPoints(RectangleF rect) { - rgbaRenderer.DrawSprite( mapSpawnPointSprite, - new float2(rect.X, rect.Y), "chrome", new float2(rect.Width, rect.Height)); + var points = world.Map.SpawnPoints + .Select( (sp,i) => Pair.New(sp,world.players.Values.FirstOrDefault( + p => p.SpawnPointIndex == i + 1 ) )) + .ToList(); + + foreach (var p in points) + { + var pos = TransformCellToMinimapPixel(rect, p.First); + + if (p.Second == null) + rgbaRenderer.DrawSprite(unownedSpawnPoint, pos, "chrome"); + else + { + lineRenderer.FillRect(new RectangleF( + Game.viewport.Location.X + pos.X + 2, + Game.viewport.Location.Y + pos.Y + 2, + 12, 12), p.Second.Color); + + rgbaRenderer.DrawSprite(ownedSpawnPoint, pos, "chrome"); + } + } + + lineRenderer.Flush(); rgbaRenderer.Flush(); } } diff --git a/artsrc/ra/spawnpoints.psd b/artsrc/ra/spawnpoints.psd new file mode 100644 index 0000000000..5e289493cb Binary files /dev/null and b/artsrc/ra/spawnpoints.psd differ diff --git a/mods/cnc/chrome.xml b/mods/cnc/chrome.xml index 6fb828115f..2e3a056140 100644 --- a/mods/cnc/chrome.xml +++ b/mods/cnc/chrome.xml @@ -143,4 +143,8 @@ + + + + diff --git a/mods/cnc/spawnpoints.png b/mods/cnc/spawnpoints.png new file mode 100644 index 0000000000..d889ecdcb7 Binary files /dev/null and b/mods/cnc/spawnpoints.png differ diff --git a/mods/ra/chrome.xml b/mods/ra/chrome.xml index 6fb828115f..2e3a056140 100644 --- a/mods/ra/chrome.xml +++ b/mods/ra/chrome.xml @@ -143,4 +143,8 @@ + + + + diff --git a/mods/ra/spawnpoints.png b/mods/ra/spawnpoints.png new file mode 100644 index 0000000000..d889ecdcb7 Binary files /dev/null and b/mods/ra/spawnpoints.png differ