From c28030487597543d2a5571741bcf95148572a328 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sat, 6 Feb 2010 22:51:22 +1300 Subject: [PATCH] nice spawnpoint render --- OpenRa.Game/Chrome.cs | 10 ++--- OpenRa.Game/Game.cs | 4 +- OpenRa.Game/Graphics/Minimap.cs | 77 +++++++++++++++++++++----------- artsrc/ra/spawnpoints.psd | Bin 0 -> 27510 bytes mods/cnc/chrome.xml | 4 ++ mods/cnc/spawnpoints.png | Bin 0 -> 4129 bytes mods/ra/chrome.xml | 4 ++ mods/ra/spawnpoints.png | Bin 0 -> 4129 bytes 8 files changed, 65 insertions(+), 34 deletions(-) create mode 100644 artsrc/ra/spawnpoints.psd create mode 100644 mods/cnc/spawnpoints.png create mode 100644 mods/ra/spawnpoints.png 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 0000000000000000000000000000000000000000..5e289493cbaeaa8c486898ddf4cd4a26c6e944a6 GIT binary patch literal 27510 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d889ecdcb713408eb0a55e878d21d809c81f72ae GIT binary patch literal 4129 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 KYK@9r)c*i&*nl$t literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d889ecdcb713408eb0a55e878d21d809c81f72ae GIT binary patch literal 4129 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 KYK@9r)c*i&*nl$t literal 0 HcmV?d00001