void TriangulateOpenWater(HexDirection direction, HexCell_Script cell, HexCell_Script neighbor, Vector3 center) { Vector3 c1 = center + HexMetrics_Script.GetFirstWaterCorner(direction); Vector3 c2 = center + HexMetrics_Script.GetSecondWaterCorner(direction); water.AddTriangle(center, c1, c2); if (direction <= HexDirection.SE && neighbor != null) { Vector3 bridge = HexMetrics_Script.GetWaterBridge(direction); Vector3 e1 = c1 + bridge; Vector3 e2 = c2 + bridge; water.AddQuad(c1, c2, e1, e2); if (direction <= HexDirection.E) { HexCell_Script nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor == null || !nextNeighbor.IsUnderwater) { return; } water.AddTriangle(c2, e2, c2 + HexMetrics_Script.GetWaterBridge(direction.Next())); } } }
void ErodeLand() { List <HexCell_Script> erodibleCells = ListPool <HexCell_Script> .Get(); for (int i = 0; i < cellCount; i++) { HexCell_Script cell = grid.GetCell(i); if (IsErodible(cell)) { erodibleCells.Add(cell); } } int targetErodibleCount = (int)(erodibleCells.Count * (100 - erosionPercentage) * 0.01f); while (erodibleCells.Count > targetErodibleCount) { int index = Random.Range(0, erodibleCells.Count); HexCell_Script cell = erodibleCells[index]; HexCell_Script targetCell = GetErosionTarget(cell); cell.Elevation--; targetCell.Elevation++; if (!IsErodible(cell)) { erodibleCells[index] = erodibleCells[erodibleCells.Count - 1]; erodibleCells.RemoveAt(erodibleCells.Count - 1); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neigbor = cell.GetNeighbor(d); if (neigbor && neigbor.Elevation == cell.Elevation + 2 && !erodibleCells.Contains(neigbor)) { erodibleCells.Add(neigbor); } } if (IsErodible(targetCell) && !erodibleCells.Contains(targetCell)) { erodibleCells.Add(targetCell); } for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = targetCell.GetNeighbor(d); if (neighbor && neighbor != cell && !IsErodible(neighbor) && neighbor.Elevation == targetCell.Elevation + 1) { erodibleCells.Remove(neighbor); } } } ListPool <HexCell_Script> .Add(erodibleCells); }
void ValidateDrag(HexCell_Script currentCell) { for (dragDirection = HexDirection.NE; dragDirection <= HexDirection.NW; dragDirection++) { if (previousCell.GetNeighbor(dragDirection) == currentCell) { isDrag = true; return; } } isDrag = false; }
int RaiseTerrain(int chunkSize, int budget, MapRegion region) { searchFrontierPhase++; HexCell_Script firstCell = GetRandomCell(region); firstCell.SearchPhase = searchFrontierPhase; firstCell.Distance = 0; firstCell.SearchHeuristic = 0; searchFrontier.Enqueue(firstCell); HexCoordinates center = firstCell.coordinates; int rise = Random.value < highRiseProbability ? 2 : 1; int size = 0; while (size < chunkSize && searchFrontier.Count > 0) { HexCell_Script current = searchFrontier.Dequeue(); int originalElevation = current.Elevation; int newElevation = originalElevation + rise; if (newElevation > elevationMaximum) { continue; } current.Elevation = newElevation; if (originalElevation < waterLevel && newElevation >= waterLevel && --budget == 0) { break; } size++; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = current.GetNeighbor(d); if (neighbor && neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = neighbor.coordinates.DistanceTo(center); neighbor.SearchHeuristic = Random.value < jitterProbabitlity ? 1 : 0;; searchFrontier.Enqueue(neighbor); } } } searchFrontier.Clear(); return(budget); }
bool IsErodible(HexCell_Script cell) { int erodibleElevation = cell.Elevation - 2; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = cell.GetNeighbor(d); if (neighbor && neighbor.Elevation <= erodibleElevation) { return(true); } } return(false); }
void TriangulateWater(HexDirection direction, HexCell_Script cell, Vector3 center) { center.y = cell.WaterSurfaceY; HexCell_Script neighbor = cell.GetNeighbor(direction); if (neighbor != null && !neighbor.IsUnderwater) { TriangulateWaterShore(direction, cell, neighbor, center); } else { TriangulateOpenWater(direction, cell, neighbor, center); } }
void TriangulateWaterShore(HexDirection direction, HexCell_Script cell, HexCell_Script neighbor, Vector3 center) { EdgeVertices e1 = new EdgeVertices(center + HexMetrics_Script.GetFirstWaterCorner(direction), center + HexMetrics_Script.GetSecondWaterCorner(direction)); water.AddTriangle(center, e1.v1, e1.v2); water.AddTriangle(center, e1.v2, e1.v3); water.AddTriangle(center, e1.v3, e1.v4); water.AddTriangle(center, e1.v4, e1.v5); Vector3 center2 = neighbor.Position; center2.y = center.y; EdgeVertices e2 = new EdgeVertices(center2 + HexMetrics_Script.GetSecondSolidCorner(direction.Opposite()), center2 + HexMetrics_Script.GetFirstSolidCorner(direction.Opposite())); if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(e1, e2, cell.IncomingRiver == direction); } else { waterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); waterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); waterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); waterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); } HexCell_Script nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { Vector3 v3 = nextNeighbor.Position + (nextNeighbor.IsUnderwater ? HexMetrics_Script.GetFirstWaterCorner(direction.Previous()) : HexMetrics_Script.GetFirstSolidCorner(direction.Previous())); v3.y = center.y; waterShore.AddTriangle(e1.v5, e2.v5, v3); waterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbor.IsUnderwater?0f:1f)); } }
HexCell_Script GetErosionTarget(HexCell_Script cell) { List <HexCell_Script> candidates = ListPool <HexCell_Script> .Get(); int erodibleElavation = cell.Elevation - 2; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = cell.GetNeighbor(d); if (neighbor && neighbor.Elevation <= erodibleElavation) { candidates.Add(neighbor); } } HexCell_Script target = candidates[Random.Range(0, candidates.Count)]; ListPool <HexCell_Script> .Add(candidates); return(target); }
bool Search(HexCell_Script fromCell, HexCell_Script toCell, int speed) { searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } //WaitForSeconds delay = new WaitForSeconds(1 / 60f); fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { //yield return delay; HexCell_Script current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current.SearchPhase == 10000) { Debug.LogError("Could not find Path after 10000 searches!"); return(false); } if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell_Script neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.IsUnderwater || neighbor.Unit) { continue; } HexEdgeType edgeType = current.GetEdgeType(neighbor); if (edgeType == HexEdgeType.Cliff) { continue; } int moveCost; if (current.HasRoadThroughEdge(d)) { moveCost = 1; } else if (current.Walled != neighbor.Walled) { continue; } else { moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; } int distance = current.Distance + moveCost; int turn = distance / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; //neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } //searchFrontier.Sort((x, y) => x.SearchPriority.CompareTo(y.SearchPriority)); } } return(false); }
void TriangulateConnection(HexDirection direction, HexCell_Script cell, EdgeVertices e1) { HexCell_Script neighbor = cell.GetNeighbor(direction); if (neighbor == null) { return; } Vector3 bridge = HexMetrics_Script.GetBridge(direction); bridge.y = neighbor.Position.y - cell.Position.y; EdgeVertices e2 = new EdgeVertices(e1.v1 + bridge, e1.v5 + bridge); bool hasRiver = cell.HasRiverThroughEdge(direction); bool hasRoad = cell.HasRoadThroughEdge(direction); if (hasRiver) { e2.v3.y = neighbor.StreamBedY; if (!cell.IsUnderwater) { if (!neighbor.IsUnderwater) { TriangulateRiverQuad(e1.v2, e1.v4, e2.v2, e2.v4, cell.HasIncomingRiver && cell.IncomingRiver == direction, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f); } else if (cell.Elevation > neighbor.WaterLevel) { TriangulateWaterfallInWater(e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, neighbor.WaterSurfaceY); } } else if (!neighbor.IsUnderwater && neighbor.Elevation > cell.WaterLevel) { TriangulateWaterfallInWater(e2.v4, e2.v2, e1.v4, e1.v2, neighbor.RiverSurfaceY, cell.RiverSurfaceY, cell.WaterSurfaceY); } } if (cell.GetEdgeType(direction) == HexEdgeType.Slope) { TriangulateEdgeTerraces(e1, cell, e2, neighbor, hasRoad); } else { TriangulateEdgeStrip(e1, color1, cell.TerrainTypeIndex, e2, color2, neighbor.TerrainTypeIndex, hasRoad); } features.AddWall(e1, cell, e2, neighbor, hasRiver, hasRoad); HexCell_Script nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null && direction <= HexDirection.E) { Vector3 v5 = e1.v5 + HexMetrics_Script.GetBridge(direction.Next()); v5.y = nextNeighbor.Position.y; if (cell.Elevation <= neighbor.Elevation) { if (cell.Elevation <= nextNeighbor.Elevation) { TriangulateCorner(e1.v5, cell, e2.v5, neighbor, v5, nextNeighbor); } else { TriangulateCorner(v5, nextNeighbor, e1.v5, cell, e2.v5, neighbor); } } else if (neighbor.Elevation <= nextNeighbor.Elevation) { TriangulateCorner(e2.v5, neighbor, v5, nextNeighbor, e1.v5, cell); } else { TriangulateCorner(v5, nextNeighbor, e1.v5, cell, e2.v5, neighbor); } //AddTriangle(v2, v5, v5); //AddTriangleColor(cell.color, neighbor.color, nextNeighbor.color); } }
void EditCell(HexCell_Script cell) { if (cell) { //if (applyColor) // cell.Color = activeColor; if (activeTerrainTypeIndex >= 0) { cell.TerrainTypeIndex = activeTerrainTypeIndex; } if (applyElevation) { cell.Elevation = activeElevation; } if (applyWaterLevel) { cell.WaterLevel = activeWaterLevel; } if (applySpecialIndex) { cell.SpecialIndex = activeSpecialIndex; } if (applyUrbanLevel) { cell.UrbanLevel = activeUrbanLevel; } if (applyFarmLevel) { cell.FarmLevel = activeFarmLevel; } if (applyPlantLevel) { cell.PlantLevel = activePlantLevel; } if (riverMode == OptionalToggle.No) { cell.RemoverRiver(); } if (roadMode == OptionalToggle.No) { cell.RemoveRoads(); } if (isDrag) { HexCell_Script otherCell = cell.GetNeighbor(dragDirection.Opposite()); if (otherCell) { if (riverMode == OptionalToggle.Yes) { otherCell.SetOutgoingRiver(dragDirection); } if (walledMode != OptionalToggle.Ignore) { cell.Walled = walledMode == OptionalToggle.Yes; } if (roadMode == OptionalToggle.Yes) { otherCell.AddRoad(dragDirection); } } } //else if (isDrag && riverMode == OptionalToggle.Yes) //{ // HexCell_Script otherCell = cell.GetNeighbor(dragDirection.Opposite()); // if (otherCell) // otherCell.SetOutgoingRiver(dragDirection); //} } }