diff --git a/C7/MapView.cs b/C7/MapView.cs index 2202fb6b..205c4486 100644 --- a/C7/MapView.cs +++ b/C7/MapView.cs @@ -408,9 +408,11 @@ 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 riverDeltaTexture; public RiverLayer() { riverTexture = Util.LoadTextureFromPCX("Art/Terrain/mtnRivers.pcx"); + riverDeltaTexture = Util.LoadTextureFromPCX("Art/Terrain/deltaRivers.pcx"); } public override void drawObject(LooseView looseView, GameData gameData, Tile tile, Vector2 tileCenter) @@ -423,6 +425,10 @@ public override void drawObject(LooseView looseView, GameData gameData, Tile til Tile westOfPoint = tile; Tile southOfPoint = tile.neighbors[TileDirection.SOUTHEAST]; + List neighbors = new List () {northOfPoint, eastOfPoint, westOfPoint, southOfPoint}; + + int coastCount =neighbors.Sum(tile => tile.IsWater()== true ? 1 : 0); + int riverGraphicsIndex = 0; if (northOfPoint.riverSouthwest) { @@ -445,7 +451,15 @@ public override void drawObject(LooseView looseView, GameData gameData, Tile til 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); + if(coastCount < 2 ) + { + looseView.DrawTextureRectRegion(riverTexture, screenTarget, riverRectangle); + } + else + { + looseView.DrawTextureRectRegion(riverDeltaTexture, screenTarget, riverRectangle); + } + } } diff --git a/C7GameData/Tile.cs b/C7GameData/Tile.cs index d62b85d2..729d8856 100644 --- a/C7GameData/Tile.cs +++ b/C7GameData/Tile.cs @@ -4,6 +4,8 @@ namespace C7GameData using System.Text.Json.Serialization; using System.Collections.Generic; using System.Linq; + using System.Diagnostics.Tracing; + public class Tile { // ExtraInfo will eventually be type object and use a type descriminator in JSON to determine @@ -53,6 +55,9 @@ public class Tile public bool riverWest; public bool riverNorthwest; + // -1 = not initialized. 0 = false, 1 = true + public int isLake = -1; + public TileOverlays overlays = new TileOverlays(); public Tile() @@ -144,6 +149,112 @@ public bool IsAllowCities() { return overlayTerrainType.allowCities; } + public bool IsLake() + { + // If the isLake value has been initialized, we should return that + if(isLake != -1) + { + return (isLake == 1); + } + + if(!IsWater()) + { + isLake = 0; + return false; + } + + int contiguousWater = 1; + List contiguous = new List(); + List searchedWater = new List(); + contiguous.Add(this); + bool lake = false; + + + while(contiguous.Count != 0) + { + Tile currentTile = contiguous[0]; + + // Skip land tiles and remove from the stack. This should be checked before they're added but just in case + if(!currentTile.IsWater()) + { + currentTile.isLake = 0; + contiguous.Remove(currentTile); + continue; + } + contiguousWater += 1; + if(contiguousWater > 20) + { + lake = true; + break; + } + + // If a contiguous tile is a lake, this (and all contiguous water) is too. This works because contiguousness is transitive. If it is *not* a lake (and is a water tile), then this isn't either. + if(currentTile.isLake == 1) + { + lake = true; + break; + } + if(currentTile.isLake == 0) + { + lake = false; + break; + } + // If we haven't found out one way or the other, add all of this tile's water neighbors to the stack and then remove this tile + foreach((TileDirection dir, Tile neighbor) in currentTile.neighbors) + { + if(!neighbor.IsWater()) + { + continue; + } + else if(contiguous.Contains(neighbor) || searchedWater.Contains(neighbor)) + { + continue; + } + else + { + // Add neighbor to tiles we should search + contiguous.Add(neighbor); + } + } + contiguous.Remove(currentTile); + searchedWater.Add(currentTile); + } + if(lake) + { + // Update all the contiguous water tiles we've looked at. It won't be the whole body of water but it'll save us some repeats. + foreach(Tile currentTile in contiguous) + { + if(currentTile.IsWater()) + { + currentTile.isLake = 1; + } + } + foreach(Tile currentTile in searchedWater) + { + currentTile.isLake = 1; + } + return true; + } + else + { + // Update searched water as non-lake. + foreach(Tile currentTile in contiguous) + { + currentTile.isLake = 0; + } + foreach(Tile currentTile in searchedWater) + { + currentTile.isLake = 0; + } + return false; + } + } + + public bool providesFreshWater () + { + return IsLake() || BordersRiver(); + } + public TileDirection directionTo(Tile other) { // TODO: Consider edge wrapping, the direction should point along the shortest path as the crow flies.