private void SetRiverTile(River river) { SetRiverPath(river); //HeightType = HeightType.River; IsRiver = true; //HeightValue = 0; IsCollidable = false; }
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 = mapData.Tiles[x, y]; // validate the tile if (!tile.IsCollidable) { 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 (!IsCollidable) { return; } if (!Rivers.Contains(river)) { Rivers.Add(river); } }
public int GetRiverNeighborCount(River river) { int count = 0; if (Left.Rivers.Count > 0 && Left.Rivers.Contains(river)) { count++; } if (Right.Rivers.Count > 0 && Right.Rivers.Contains(river)) { count++; } if (Top.Rivers.Count > 0 && Top.Rivers.Contains(river)) { count++; } if (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.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(left)) { leftValue = left.HeightValue; } if (right.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(right)) { rightValue = right.HeightValue; } if (top.GetRiverNeighborCount(river) < 2 && !river.Tiles.Contains(top)) { topValue = top.HeightValue; } if (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.Rivers.Count == 0 && !bottom.IsCollidable) { bottomValue = 0; } if (top.Rivers.Count == 0 && !top.IsCollidable) { topValue = 0; } if (left.Rivers.Count == 0 && !left.IsCollidable) { leftValue = 0; } if (right.Rivers.Count == 0 && !right.IsCollidable) { 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 = (float)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.IsCollidable) { if (river.CurrentDirection != Direction.Left) { river.TurnCount++; river.CurrentDirection = Direction.Left; } FindPathToWater(left, direction, ref river); } } else if (min == rightValue) { if (right.IsCollidable) { if (river.CurrentDirection != Direction.Right) { river.TurnCount++; river.CurrentDirection = Direction.Right; } FindPathToWater(right, direction, ref river); } } else if (min == bottomValue) { if (bottom.IsCollidable) { if (river.CurrentDirection != Direction.Bottom) { river.TurnCount++; river.CurrentDirection = Direction.Bottom; } FindPathToWater(bottom, direction, ref river); } } else if (min == topValue) { if (top.IsCollidable) { if (river.CurrentDirection != Direction.Top) { river.TurnCount++; river.CurrentDirection = Direction.Top; } FindPathToWater(top, direction, ref river); } } }
// 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 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++; } }
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 = mapData.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); } } } } }
public void DigRiver(River river, int size) { SetRiverTile(river); RiverSize = size; if (size == 1) { Bottom.SetRiverTile(river); Right.SetRiverTile(river); Bottom.Right.SetRiverTile(river); } if (size == 2) { Bottom.SetRiverTile(river); Right.SetRiverTile(river); Bottom.Right.SetRiverTile(river); Top.SetRiverTile(river); Top.Left.SetRiverTile(river); Top.Right.SetRiverTile(river); Left.SetRiverTile(river); Left.Bottom.SetRiverTile(river); } if (size == 3) { Bottom.SetRiverTile(river); Right.SetRiverTile(river); Bottom.Right.SetRiverTile(river); Top.SetRiverTile(river); Top.Left.SetRiverTile(river); Top.Right.SetRiverTile(river); Left.SetRiverTile(river); Left.Bottom.SetRiverTile(river); Right.Right.SetRiverTile(river); Right.Right.Bottom.SetRiverTile(river); Bottom.Bottom.SetRiverTile(river); Bottom.Bottom.Right.SetRiverTile(river); } if (size == 4) { Bottom.SetRiverTile(river); Right.SetRiverTile(river); Bottom.Right.SetRiverTile(river); Top.SetRiverTile(river); Top.Right.SetRiverTile(river); Left.SetRiverTile(river); Left.Bottom.SetRiverTile(river); Right.Right.SetRiverTile(river); Right.Right.Bottom.SetRiverTile(river); Bottom.Bottom.SetRiverTile(river); Bottom.Bottom.Right.SetRiverTile(river); Left.Bottom.Bottom.SetRiverTile(river); Left.Left.Bottom.SetRiverTile(river); Left.Left.SetRiverTile(river); Left.Left.Top.SetRiverTile(river); Left.Top.SetRiverTile(river); Left.Top.Top.SetRiverTile(river); Top.Top.SetRiverTile(river); Top.Top.Right.SetRiverTile(river); Top.Right.Right.SetRiverTile(river); } }