private void SetRiverTile(River river) { SetRiverPath(river); HeightType = HeightType.River; HeightValue = 0; Collidable = false; }
private void GenerateRivers() { int attempts = 0; int rivercount = RiverCount; Rivers = new List <River>(); // Generate some rivers while (rivercount > 0 && attempts < MaxRiverAttempts) { // Get a random tile int x = Random.Next(0, Width); int y = Random.Next(0, Height); Tile tile = Tiles[x, y]; // validate the tile if (!tile.Collidable) { continue; } if (tile.Rivers.Count > 0) { continue; } if (tile.HeightValue > MinRiverHeight) { // Tile is good to start river from River river = new River(rivercount); // Figure out the direction this river will try to flow river.CurrentDirection = tile.GetLowestNeighbor(); // Recursively find a path to water FindPathToWater(tile, river.CurrentDirection, ref river); // Validate the generated river if (river.TurnCount < MinRiverTurns || river.Tiles.Count < MinRiverLength || river.Intersections > MaxRiverIntersections) { //Validation failed - remove this river for (int i = 0; i < river.Tiles.Count; i++) { Tile t = river.Tiles[i]; t.Rivers.Remove(river); } } else if (river.Tiles.Count >= MinRiverLength) { //Validation passed - Add river to list Rivers.Add(river); tile.Rivers.Add(river); rivercount--; } } attempts++; } }
public void SetRiverPath(River river) { if (!Collidable) { return; } if (!Rivers.Contains(river)) { Rivers.Add(river); } }
public int GetRiverNeighborCount(River river) { int count = 0; if (Left != null && Left.Rivers.Count > 0 && Left.Rivers.Contains(river)) { count++; } if (Right != null && Right.Rivers.Count > 0 && Right.Rivers.Contains(river)) { count++; } if (Top != null && Top.Rivers.Count > 0 && Top.Rivers.Contains(river)) { count++; } if (Bottom != null && Bottom.Rivers.Count > 0 && Bottom.Rivers.Contains(river)) { count++; } return(count); }
private void DigRiverGroups() { for (int i = 0; i < RiverGroups.Count; i++) { RiverGroup group = RiverGroups[i]; River longest = null; //Find longest river in this group for (int j = 0; j < group.Rivers.Count; j++) { River river = group.Rivers[j]; if (longest == null) { longest = river; } else if (longest.Tiles.Count < river.Tiles.Count) { longest = river; } } if (longest != null) { //Dig out longest path first DigRiver(longest); for (int j = 0; j < group.Rivers.Count; j++) { River river = group.Rivers[j]; if (river != longest) { DigRiver(river, longest); } } } } }
private void FindPathToWater(Tile tile, Direction direction, ref River river) { if (tile.Rivers.Contains(river)) { return; } // check if there is already a river on this tile if (tile.Rivers.Count > 0) { river.Intersections++; } river.AddTile(tile); // get neighbors Tile left = GetLeft(tile); Tile right = GetRight(tile); Tile top = GetTop(tile); Tile bottom = GetBottom(tile); float leftValue = int.MaxValue; float rightValue = int.MaxValue; float topValue = int.MaxValue; float bottomValue = int.MaxValue; // query height values of neighbors if (left != null && left.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(left)) { leftValue = left.HeightValue; } if (right != null && right.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(right)) { rightValue = right.HeightValue; } if (top != null && top.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(top)) { topValue = top.HeightValue; } if (bottom != null && bottom.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(bottom)) { bottomValue = bottom.HeightValue; } // if neighbor is existing river that is not this one, flow into it if (bottom != null && bottom.Rivers.Count == 0 && !bottom.Collidable) { bottomValue = 0; } if (top != null && top.Rivers.Count == 0 && !top.Collidable) { topValue = 0; } if (left != null && left.Rivers.Count == 0 && !left.Collidable) { leftValue = 0; } if (right != null && right.Rivers.Count == 0 && !right.Collidable) { rightValue = 0; } // override flow direction if a tile is significantly lower if (direction == Direction.Left) { if (Math.Abs(rightValue - leftValue) < 0.1f) { rightValue = int.MaxValue; } } if (direction == Direction.Right) { if (Math.Abs(rightValue - leftValue) < 0.1f) { leftValue = int.MaxValue; } } if (direction == Direction.Top) { if (Math.Abs(topValue - bottomValue) < 0.1f) { bottomValue = int.MaxValue; } } if (direction == Direction.Bottom) { if (Math.Abs(topValue - bottomValue) < 0.1f) { topValue = int.MaxValue; } } // find mininum float min = Math.Min(Math.Min(Math.Min(leftValue, rightValue), topValue), bottomValue); // if no minimum found - exit if (min == int.MaxValue) { return; } //Move to next neighbor if (min == leftValue) { if (left != null && left.Collidable) { if (river.CurrentDirection != Direction.Left) { river.TurnCount++; river.CurrentDirection = Direction.Left; } FindPathToWater(left, direction, ref river); } } else if (min == rightValue) { if (right != null && right.Collidable) { if (river.CurrentDirection != Direction.Right) { river.TurnCount++; river.CurrentDirection = Direction.Right; } FindPathToWater(right, direction, ref river); } } else if (min == bottomValue) { if (bottom != null && bottom.Collidable) { if (river.CurrentDirection != Direction.Bottom) { river.TurnCount++; river.CurrentDirection = Direction.Bottom; } FindPathToWater(bottom, direction, ref river); } } else if (min == topValue) { if (top != null && top.Collidable) { if (river.CurrentDirection != Direction.Top) { river.TurnCount++; river.CurrentDirection = Direction.Top; } FindPathToWater(top, direction, ref river); } } }
// Dig river private void DigRiver(River river) { int counter = 0; // How wide are we digging this river? int size = Random.Next(1, 5); river.Length = river.Tiles.Count; // randomize size change int two = river.Length / 2; int three = two / 2; int four = three / 2; int five = four / 2; int twomin = two / 3; int threemin = three / 3; int fourmin = four / 3; int fivemin = five / 3; // randomize lenght of each size int count1 = Random.Next(fivemin, five); if (size < 4) { count1 = 0; } int count2 = count1 + Random.Next(fourmin, four); if (size < 3) { count2 = 0; count1 = 0; } int count3 = count2 + Random.Next(threemin, three); if (size < 2) { count3 = 0; count2 = 0; count1 = 0; } int count4 = count3 + Random.Next(twomin, two); // Make sure we are not digging past the river path if (count4 > river.Length) { int extra = count4 - river.Length; while (extra > 0) { if (count1 > 0) { count1--; count2--; count3--; count4--; extra--; } else if (count2 > 0) { count2--; count3--; count4--; extra--; } else if (count3 > 0) { count3--; count4--; extra--; } else if (count4 > 0) { count4--; extra--; } } } // Dig it out for (int i = river.Tiles.Count - 1; i >= 0; i--) { Tile t = river.Tiles[i]; if (counter < count1) { t.DigRiver(river, 4); } else if (counter < count2) { t.DigRiver(river, 3); } else if (counter < count3) { t.DigRiver(river, 2); } else if (counter < count4) { t.DigRiver(river, 1); } else { t.DigRiver(river, 0); } counter++; } }
// Dig river based on a parent river vein private void DigRiver(River river, River parent) { int intersectionID = 0; int intersectionSize = 0; // determine point of intersection for (int i = 0; i < river.Tiles.Count; i++) { Tile t1 = river.Tiles[i]; for (int j = 0; j < parent.Tiles.Count; j++) { Tile t2 = parent.Tiles[j]; if (t1 == t2) { intersectionID = i; intersectionSize = t2.RiverSize; } } } int counter = 0; int intersectionCount = river.Tiles.Count - intersectionID; int size = Random.Next(intersectionSize, 5); river.Length = river.Tiles.Count; // randomize size change int two = river.Length / 2; int three = two / 2; int four = three / 2; int five = four / 2; int twomin = two / 3; int threemin = three / 3; int fourmin = four / 3; int fivemin = five / 3; // randomize length of each size int count1 = Random.Next(fivemin, five); if (size < 4) { count1 = 0; } int count2 = count1 + Random.Next(fourmin, four); if (size < 3) { count2 = 0; count1 = 0; } int count3 = count2 + Random.Next(threemin, three); if (size < 2) { count3 = 0; count2 = 0; count1 = 0; } int count4 = count3 + Random.Next(twomin, two); // Make sure we are not digging past the river path if (count4 > river.Length) { int extra = count4 - river.Length; while (extra > 0) { if (count1 > 0) { count1--; count2--; count3--; count4--; extra--; } else if (count2 > 0) { count2--; count3--; count4--; extra--; } else if (count3 > 0) { count3--; count4--; extra--; } else if (count4 > 0) { count4--; extra--; } } } // adjust size of river at intersection point if (intersectionSize == 1) { count4 = intersectionCount; count1 = 0; count2 = 0; count3 = 0; } else if (intersectionSize == 2) { count3 = intersectionCount; count1 = 0; count2 = 0; } else if (intersectionSize == 3) { count2 = intersectionCount; count1 = 0; } else if (intersectionSize == 4) { count1 = intersectionCount; } else { count1 = 0; count2 = 0; count3 = 0; count4 = 0; } // dig out the river for (int i = river.Tiles.Count - 1; i >= 0; i--) { Tile t = river.Tiles[i]; if (counter < count1) { t.DigRiver(river, 4); } else if (counter < count2) { t.DigRiver(river, 3); } else if (counter < count3) { t.DigRiver(river, 2); } else if (counter < count4) { t.DigRiver(river, 1); } else { t.DigRiver(river, 0); } counter++; } }
private void BuildRiverGroups() { //loop each tile, checking if it belongs to multiple rivers for (var x = 0; x < Width; x++) { for (var y = 0; y < Height; y++) { Tile t = Tiles[x, y]; if (t.Rivers.Count > 1) { // multiple rivers == intersection RiverGroup group = null; // Does a rivergroup already exist for this group? for (int n = 0; n < t.Rivers.Count; n++) { River tileriver = t.Rivers[n]; for (int i = 0; i < RiverGroups.Count; i++) { for (int j = 0; j < RiverGroups[i].Rivers.Count; j++) { River river = RiverGroups[i].Rivers[j]; if (river.ID == tileriver.ID) { group = RiverGroups[i]; } if (group != null) { break; } } if (group != null) { break; } } if (group != null) { break; } } // existing group found -- add to it if (group != null) { for (int n = 0; n < t.Rivers.Count; n++) { if (!group.Rivers.Contains(t.Rivers[n])) { group.Rivers.Add(t.Rivers[n]); } } } else //No existing group found - create a new one { group = new RiverGroup(); for (int n = 0; n < t.Rivers.Count; n++) { group.Rivers.Add(t.Rivers[n]); } RiverGroups.Add(group); } } } } }
// This function got messy. Sorry. public void DigRiver(River river, int size) { SetRiverTile(river); RiverSize = size; if (size == 1) { if (Bottom != null) { Bottom.SetRiverTile(river); if (Bottom.Right != null) { Bottom.Right.SetRiverTile(river); } } if (Right != null) { Right.SetRiverTile(river); } } if (size == 2) { if (Bottom != null) { Bottom.SetRiverTile(river); if (Bottom.Right != null) { Bottom.Right.SetRiverTile(river); } } if (Right != null) { Right.SetRiverTile(river); } if (Top != null) { Top.SetRiverTile(river); if (Top.Left != null) { Top.Left.SetRiverTile(river); } if (Top.Right != null) { Top.Right.SetRiverTile(river); } } if (Left != null) { Left.SetRiverTile(river); if (Left.Bottom != null) { Left.Bottom.SetRiverTile(river); } } } if (size == 3) { if (Bottom != null) { Bottom.SetRiverTile(river); if (Bottom.Right != null) { Bottom.Right.SetRiverTile(river); } if (Bottom.Bottom != null) { Bottom.Bottom.SetRiverTile(river); if (Bottom.Bottom.Right != null) { Bottom.Bottom.Right.SetRiverTile(river); } } } if (Right != null) { Right.SetRiverTile(river); if (Right.Right != null) { Right.Right.SetRiverTile(river); if (Right.Right.Bottom != null) { Right.Right.Bottom.SetRiverTile(river); } } } if (Top != null) { Top.SetRiverTile(river); if (Top.Left != null) { Top.Left.SetRiverTile(river); } if (Top.Right != null) { Top.Right.SetRiverTile(river); } } if (Left != null) { Left.SetRiverTile(river); if (Left.Bottom != null) { Left.Bottom.SetRiverTile(river); } } } if (size == 4) { if (Bottom != null) { Bottom.SetRiverTile(river); if (Bottom.Right != null) { Bottom.Right.SetRiverTile(river); } if (Bottom.Bottom != null) { Bottom.Bottom.SetRiverTile(river); if (Bottom.Bottom.Right != null) { Bottom.Bottom.Right.SetRiverTile(river); } } } if (Right != null) { Right.SetRiverTile(river); if (Right.Right != null) { Right.Right.SetRiverTile(river); if (Right.Right.Bottom != null) { Right.Right.Bottom.SetRiverTile(river); } } } if (Top != null) { Top.SetRiverTile(river); if (Top.Right != null) { Top.Right.SetRiverTile(river); if (Top.Right.Right != null) { Top.Right.Right.SetRiverTile(river); } } if (Top.Top != null) { Top.Top.SetRiverTile(river); if (Top.Top.Right != null) { Top.Top.Right.SetRiverTile(river); } } } if (Left != null) { Left.SetRiverTile(river); if (Left.Bottom != null) { Left.Bottom.SetRiverTile(river); if (Left.Bottom.Bottom != null) { Left.Bottom.Bottom.SetRiverTile(river); } } if (Left.Left != null) { Left.Left.SetRiverTile(river); if (Left.Left.Bottom != null) { Left.Left.Bottom.SetRiverTile(river); } if (Left.Left.Top != null) { Left.Left.Top.SetRiverTile(river); } } if (Left.Top != null) { Left.Top.SetRiverTile(river); if (Left.Top.Top != null) { Left.Top.Top.SetRiverTile(river); } } } } }