// Set the river tile at the given corner position (and wrapped // positions if necessary) protected virtual void SetRiverTile(int x, int y, RiverTile tile) { currentRiverMap.SetTile(new Vector3Int(x, y, 0), tile); // If the river is on a wrapping edge, place the same river tile on // the opposite side bool wrapX = parameters.WrapX && (x == 0 || x == parameters.Width); bool wrapY = parameters.WrapY && (y == 0 || y == parameters.Height); if (wrapX) { // Horizontally currentRiverMap.SetTile( new Vector3Int(parameters.Width - x, y, 0), tile); } if (wrapY) { // Vertically currentRiverMap.SetTile( new Vector3Int(x, parameters.Height - y, 0), tile); } if (wrapX && wrapY) { // Corner wrapping in both dimensions currentRiverMap.SetTile( new Vector3Int(parameters.Width - x, parameters.Height - y, 0), tile); } }
// Place rivers on the map protected virtual void GenerateRivers() { // In non-wrapping dimensions, there are more corners than tiles int cornersWidth = parameters.Width; if (!parameters.WrapX) { cornersWidth++; } int cornersHeight = parameters.Height; if (!parameters.WrapY) { cornersHeight++; } // Check all tile corners for (int i = 0; i < cornersHeight; i++) { for (int j = 0; j < cornersWidth; j++) { // Try to get the river tile at the corner RiverTile currentCorner = currentRiverMap.GetTile <RiverTile>( new Vector3Int(j, i, 0)); // Skip if there is already a river here or if next to // ocean if (currentCorner || CornerAtOcean(j, i)) { continue; } // Certain probability of starting river if (Random.value < RiverProbability(j, i)) { ContinueRiver(j, i, 0); } } } }
// Place a river at the given corner, then determine the next corner in // the river and, if necessary, call this function for that corner // prevDirection is the direction that the previous corner is in protected virtual void ContinueRiver( int x, int y, RiverTile.Directions prevDirection) { // Create the new river tile and set its connection to the previous // one RiverTile newTile = ScriptableObject.CreateInstance <RiverTile>(); newTile.Parameters = parameters; newTile.LandTilemap = currentMap; newTile.Connections = prevDirection; // Stop if reached ocean if (!CornerAtOcean(x, y)) { // Next river tile is down the steepest downslope int nextX, nextY; SteepestSlope(x, y, out nextX, out nextY); // Stop if there is no downslope if (nextX != -1 && nextY != -1) { // Try to get existing river tile at next position RiverTile nextCorner = currentRiverMap.GetTile <RiverTile>( new Vector3Int(nextX, nextY, 0)); // Check direction of next river tile // Left if (nextX < x) { // Set connection to the next river tile newTile.Connections |= RiverTile.Directions.Left; // If next river tile already exists, set its // connection to the current tile and stop if (nextCorner) { nextCorner.Connections |= RiverTile.Directions.Right; } // Recursively continue river generation else { ContinueRiver( nextX, nextY, RiverTile.Directions.Right); } } // Right else if (nextX > x) { newTile.Connections |= RiverTile.Directions.Right; if (nextCorner) { nextCorner.Connections |= RiverTile.Directions.Left; } else { ContinueRiver( nextX, nextY, RiverTile.Directions.Left); } } // Up else if (nextY > y) { newTile.Connections |= RiverTile.Directions.Up; if (nextCorner) { nextCorner.Connections |= RiverTile.Directions.Down; } else { ContinueRiver( nextX, nextY, RiverTile.Directions.Down); } } // Down else if (nextY < y) { newTile.Connections |= RiverTile.Directions.Down; if (nextCorner) { nextCorner.Connections |= RiverTile.Directions.Up; } else { ContinueRiver( nextX, nextY, RiverTile.Directions.Up); } } // Replace next corner with updated connections if (nextCorner) { SetRiverTile(nextX, nextY, null); SetRiverTile(nextX, nextY, nextCorner); } } } SetRiverTile(x, y, newTile); }