diff --git a/C7/Lua/texture_configs/civ3/terrain.lua b/C7/Lua/texture_configs/civ3/terrain.lua index 4802b8743..5c43e655b 100644 --- a/C7/Lua/texture_configs/civ3/terrain.lua +++ b/C7/Lua/texture_configs/civ3/terrain.lua @@ -86,6 +86,8 @@ terrain.marsh = { terrain.river = TERRAIN .. "mtnRivers.pcx" +terrain.river_delta = TERRAIN .. "deltaRivers.pcx" + terrain.tnt = TERRAIN .. "tnt.pcx" terrain.jungle = { diff --git a/C7/MapView.cs b/C7/MapView.cs index 6eba19749..f048690f6 100644 --- a/C7/MapView.cs +++ b/C7/MapView.cs @@ -361,44 +361,84 @@ public override void drawObject(LooseView looseView, GameData gameData, Tile til public partial class RiverLayer : LooseLayer { public static readonly Vector2 riverSize = new Vector2(128, 64); public static readonly Vector2 riverCenterOffset = new Vector2(riverSize.X / 2, 0); - private ImageTexture riverTexture; + private ImageTexture narrowTexture; + private ImageTexture broadTexture; public RiverLayer() { - riverTexture = TextureLoader.Load("terrain.river"); + // Both textures are 4x4 grids of equal dimensions + // The narrow texture has four river deltas and 12 narrow river segments + // The broad texture has 16 broad river segments with more meandering + narrowTexture = TextureLoader.Load("terrain.river_delta"); + broadTexture = TextureLoader.Load("terrain.river"); } public override void drawObject(LooseView looseView, GameData gameData, Tile tile, Vector2 tileCenter) { - //The "point" is the easternmost point of the tile for which we are drawing rivers. - //Which river graphics to used is calculated by evaluating the tiles that neighbor - //that point. + // The point where four terrain tiles meet and where we want to center our river texture. + // It is the easternmost point of the current tile. + Vector2 thePoint = tileCenter + riverCenterOffset; + + // We draw the texture centered on the point by starting the draw from half of its width away + Vector2 drawOffset = -0.5f * riverSize; + + // The right river texture is calculated by evaluating the tiles around the point Tile northOfPoint = tile.neighbors[TileDirection.NORTHEAST]; Tile eastOfPoint = tile.neighbors[TileDirection.EAST]; - Tile westOfPoint = tile; Tile southOfPoint = tile.neighbors[TileDirection.SOUTHEAST]; + Tile westOfPoint = tile; - int riverGraphicsIndex = 0; + var (row, col, idx) = DeriveTextureIndex(northOfPoint, eastOfPoint, southOfPoint, westOfPoint); + if (row < 0 || col < 0 || idx < 0) + return; + + Rect2 riverRectangle = new Rect2(col * riverSize.X, row * riverSize.Y, riverSize); + Rect2 screenTarget = new Rect2(thePoint + drawOffset, riverSize); + + // Draw a river texture from one of the textures, depending on terrain. + // The placement calculation is the same for both river textures. + + if (idx is 1 or 2 or 4 or 8) { + // Narrow set has deltas at these indexes + if (HasWater(northOfPoint, eastOfPoint, southOfPoint, westOfPoint)) + looseView.DrawTextureRectRegion(narrowTexture, screenTarget, riverRectangle); + else + looseView.DrawTextureRectRegion(broadTexture, screenTarget, riverRectangle); + } else { + // TODO: When to draw from the broad texture? Is it semi-random? Is it based on elevation? - if (northOfPoint.riverSouthwest) { - riverGraphicsIndex++; + // Default: narrow rivers, less meandering + looseView.DrawTextureRectRegion(narrowTexture, screenTarget, riverRectangle); } - if (eastOfPoint.riverNorthwest) { - riverGraphicsIndex += 2; + } + + private static (int, int, int) DeriveTextureIndex(Tile north, Tile east, Tile south, Tile west) { + var textureIndex = 0; + + if (north.riverSouthwest || west.riverNortheast) { + textureIndex += 1; } - if (westOfPoint.riverSoutheast) { - riverGraphicsIndex += 4; + if (east.riverNorthwest || north.riverSoutheast) { + textureIndex += 2; } - if (southOfPoint.riverNortheast) { - riverGraphicsIndex += 8; + if (west.riverSoutheast || south.riverNorthwest) { + textureIndex += 4; } - if (riverGraphicsIndex == 0) { - return; + if (south.riverNortheast || east.riverSouthwest) { + textureIndex += 8; } - int riverRow = riverGraphicsIndex / 4; - int riverColumn = riverGraphicsIndex % 4; - Rect2 riverRectangle = new Rect2(riverColumn * riverSize.X, riverRow * riverSize.Y, riverSize); - Rect2 screenTarget = new Rect2(tileCenter - (float)0.5 * riverSize + riverCenterOffset, riverSize); - looseView.DrawTextureRectRegion(riverTexture, screenTarget, riverRectangle); + // Passes "The Point" only: an oasis + if (textureIndex == 0 && (north.riverSouth || east.riverWest || west.riverEast || south.riverNorth)) + return (0, 0, 0); + + if (textureIndex == 0) + return (-1, -1, -1); + + // We will index into a 4x4 texture matrix + return (textureIndex / 4, textureIndex % 4, textureIndex); + } + + private bool HasWater(Tile north, Tile east, Tile south, Tile west) { + return north.IsWater() || east.IsWater() || south.IsWater() || west.IsWater(); } }