public static TerrainData GenerateRiver(TerrainData data, TerrainSettings settings)
 {
     for (int i = 0; i < settings.numberOfRivers; i++)
     {
         // Find all potential river starting places
         List <TileData> potentialStarts = GetPotentialRiverStarts(data);
         if (potentialStarts.Count < settings.numberOfRivers)
         {
             return(data);
         }
         TileData start = potentialStarts[Random.Range(0, potentialStarts.Count)]; // pick random start
         potentialStarts.Remove(start);
         TileData oceanTile = data.GetEdgeAdjacentTilesOfType(start.xCoordinate, start.zCoordinate, TileType.OceanFloor)[0];
         start.type = TileType.RiverMouth;
         // Construct river
         List <TileData> riverPath = new List <TileData>();
         riverPath.Add(start);
         int      nextXCoordinate = start.xCoordinate + (start.xCoordinate - oceanTile.xCoordinate);
         int      nextZCoordinate = start.zCoordinate + (start.zCoordinate - oceanTile.zCoordinate);
         TileData currentTile     = data.GetTileAtCoordinates(nextXCoordinate, nextZCoordinate);
         currentTile.type = TileType.RiverStraight;
         TileData nextTile = null;
         for (int j = 0; j < settings.riverMaxLength; j++)
         {
             List <TileData> potentialNextTiles = data.GetEdgeAdjacentTilesOfType(currentTile.xCoordinate, currentTile.zCoordinate, TileType.Plains);
             potentialNextTiles.Remove(riverPath[j]);
             // Remove all left turn tiles
             for (int k = 0; k < potentialNextTiles.Count; k++)
             {
                 Vector2 pastDirection   = new Vector2(riverPath[j].xCoordinate - currentTile.xCoordinate, riverPath[j].zCoordinate - currentTile.zCoordinate);
                 Vector2 futureDirection = new Vector2(potentialNextTiles[k].xCoordinate - currentTile.xCoordinate, potentialNextTiles[k].zCoordinate - currentTile.zCoordinate);
                 if (Vector2.SignedAngle(pastDirection, futureDirection) == -90)
                 {
                     potentialNextTiles.Remove(potentialNextTiles[k]);
                 }
             }
             // If no more potential tiles, end river
             if (potentialNextTiles.Count == 0 || j == settings.riverMaxLength - 1)
             {
                 currentTile.type = TileType.RiverEnd;
             }
             else // otherwise make either straight or right turn
             {
                 nextTile = potentialNextTiles[Random.Range(0, potentialNextTiles.Count)];
                 Vector2 directionOne = new Vector2(riverPath[j].xCoordinate - currentTile.xCoordinate, riverPath[j].zCoordinate - currentTile.zCoordinate);
                 Vector2 directionTwo = new Vector2(nextTile.xCoordinate - currentTile.xCoordinate, nextTile.zCoordinate - currentTile.zCoordinate);
                 if (Vector2.SignedAngle(directionOne, directionTwo) == 90)
                 {
                     currentTile.type = TileType.RiverBendRight;
                 }
                 else if (Vector2.SignedAngle(directionOne, directionTwo) == -90)
                 {
                     currentTile.type = TileType.RiverEnd;
                 }
                 else
                 {
                     currentTile.type = TileType.RiverStraight;
                 }
             }
             // correctly orient tile
             Vector3 facingDirection = new Vector3(riverPath[j].xCoordinate - currentTile.xCoordinate, 0, riverPath[j].zCoordinate - currentTile.zCoordinate);
             facingDirection = facingDirection.normalized;
             if (facingDirection == Vector3.left)
             {
                 currentTile.Rotate(0, 90, 0);
                 currentTile.AddPosition(0, 0, settings.tileSize);
             }
             else if (facingDirection == Vector3.forward)
             {
                 currentTile.Rotate(0, 180, 0);
                 currentTile.AddPosition(settings.tileSize, 0, settings.tileSize);
             }
             else if (facingDirection == Vector3.right)
             {
                 currentTile.Rotate(0, -90, 0);
                 currentTile.AddPosition(settings.tileSize, 0, 0);
             }
             // if the river has ended, break from the loop
             if (currentTile.type == TileType.RiverEnd)
             {
                 break;
             }
             riverPath.Add(currentTile);
             currentTile = nextTile;
         }
     }
     return(data);
 }
Esempio n. 2
0
 public static TerrainData GenerateCoasts(TerrainData data, TerrainSettings settings)
 {
     // first get rid of islands/peninsulas
     data = RemoveIsolatedOceanTiles(data, settings);
     data = RemoveIslandsAndPeninsulas(data, settings);
     for (int x = 0; x < data.xSize; x++)
     {
         for (int z = 0; z < data.zSize; z++)
         {
             List <TileData> edgeAdjacentOcean = data.GetEdgeAdjacentTilesOfType(x, z, TileType.OceanFloor);
             if (!data.IsOceanTile(x, z) && edgeAdjacentOcean.Count > 0)
             {
                 if (edgeAdjacentOcean.Count == 1) // coastal straight
                 {
                     Vector3 direction = edgeAdjacentOcean[0].Position - data.GetTileAtCoordinates(x, z).Position;
                     direction = direction.normalized;
                     Vector3  position = new Vector3(x * settings.tileSize, 0, z * settings.tileSize);
                     TileData tile     = data.GetTileAtCoordinates(x, z);
                     tile.ReplaceTile(TileType.CoastStraight, position, Vector3.zero);
                     if (direction == -Vector3.forward)
                     {
                         tile.Rotate(0, 180, 0);
                         tile.AddPosition(new Vector3(settings.tileSize, 0, settings.tileSize));
                     }
                     else if (direction == Vector3.right)
                     {
                         tile.Rotate(0, 90, 0);
                         tile.AddPosition(new Vector3(0, 0, settings.tileSize));
                     }
                     else if (direction == -Vector3.right)
                     {
                         tile.Rotate(0, 270, 0);
                         tile.AddPosition(new Vector3(settings.tileSize, 0, 0));
                     }
                 }
                 else if (edgeAdjacentOcean.Count == 2)
                 {
                     Vector3 directionOne = edgeAdjacentOcean[0].Position - data.GetTileAtCoordinates(x, z).Position;
                     directionOne = directionOne.normalized;
                     Vector3 directionTwo = edgeAdjacentOcean[1].Position - data.GetTileAtCoordinates(x, z).Position;
                     directionTwo = directionTwo.normalized;
                     if (Vector3.Angle(directionOne, directionTwo) <= 90) // coastal outer corner
                     {
                         Vector3  position = new Vector3(x * settings.tileSize, 0, z * settings.tileSize);
                         TileData tile     = data.GetTileAtCoordinates(x, z);
                         tile.ReplaceTile(TileType.CoastOuterCorner, position, Vector3.zero);
                         if (directionOne == Vector3.forward && directionTwo == -Vector3.right || directionTwo == Vector3.forward && directionOne == -Vector3.right)
                         {
                             tile.Rotate(0, -90, 0);
                             tile.AddPosition(new Vector3(settings.tileSize, 0, 0));
                         }
                         else if (directionOne == Vector3.right && directionTwo == -Vector3.forward || directionTwo == Vector3.right && directionOne == -Vector3.forward)
                         {
                             tile.Rotate(0, 90, 0);
                             tile.AddPosition(new Vector3(0, 0, settings.tileSize));
                         }
                         else if (directionOne == -Vector3.forward && directionTwo == -Vector3.right || directionTwo == -Vector3.forward && directionOne == -Vector3.right)
                         {
                             tile.Rotate(0, 180, 0);
                             tile.AddPosition(new Vector3(settings.tileSize, 0, settings.tileSize));
                         }
                     }
                 }
             }
             List <TileData> cornerAdjacentOcean = data.GetCornerAdjacentTilesOfType(x, z, TileType.OceanFloor);
             if (cornerAdjacentOcean.Count == 1 && edgeAdjacentOcean.Count == 0) // coastal inner corner
             {
                 Vector3 direction = cornerAdjacentOcean[0].Position - data.GetTileAtCoordinates(x, z).Position;
                 direction = direction.normalized;
                 Vector3  position = new Vector3(x * settings.tileSize, 0, z * settings.tileSize);
                 TileData tile     = data.GetTileAtCoordinates(x, z);
                 tile.ReplaceTile(TileType.CoastInnerCorner, position, Vector3.zero);
                 float angle = Vector3.SignedAngle(direction, Vector3.forward, Vector3.up);
                 if (angle > 90 && angle <= 180)
                 {
                     tile.Rotate(0, -90, 0);
                     tile.AddPosition(new Vector3(settings.tileSize, 0, 0));
                 }
                 else if (angle < -90 && angle >= -180)
                 {
                     tile.Rotate(0, 180, 0);
                     tile.AddPosition(new Vector3(settings.tileSize, 0, settings.tileSize));
                 }
                 else if (angle < 0 && angle >= -90)
                 {
                     tile.Rotate(0, 90, 0);
                     tile.AddPosition(new Vector3(0, 0, settings.tileSize));
                 }
             }
         }
     }
     // do a final check for islands and peninsulas
     data = RemoveIslandsAndPeninsulas(data, settings);
     return(data);
 }