void AddWallSegment(Vector3 pivot, HexCell_Script pivotCell, Vector3 left, HexCell_Script leftCell, Vector3 right, HexCell_Script rightCell) { if (pivotCell.IsUnderwater) { return; } bool hasLeftWall = !leftCell.IsUnderwater && pivotCell.GetEdgeType(leftCell) != HexEdgeType.Cliff; bool hasRightWall = !rightCell.IsUnderwater && pivotCell.GetEdgeType(rightCell) != HexEdgeType.Cliff; if (hasLeftWall) { if (hasRightWall) { bool hasTower = false; if (leftCell.Elevation == rightCell.Elevation) { HexHash hash = HexMetrics_Script.SampleHashGrid((pivot + left + right) * (1f / 3f)); hasTower = hash.e < HexMetrics_Script.wallTowerTreshold; } AddWallSegment(pivot, left, pivot, right, hasTower); } else if (leftCell.Elevation < rightCell.Elevation) { AddWallWedge(pivot, left, right); } else { AddWallCap(pivot, left); } } else if (hasRightWall) { if (rightCell.Elevation < leftCell.Elevation) { AddWallWedge(right, pivot, left); } else { AddWallCap(right, pivot); } } }
void TriangulateCornerCliffTerraces(Vector3 begin, HexCell_Script beginCell, Vector3 left, HexCell_Script leftCell, Vector3 right, HexCell_Script rightCell) { float b = 1f / (leftCell.Elevation - beginCell.Elevation); if (b < 0) { b = -b; } Vector3 boundary = Vector3.Lerp(HexMetrics_Script.Perturb(begin), HexMetrics_Script.Perturb(left), b); Color boundaryColor = Color.Lerp(color1, color2, b); Vector3 types; types.x = beginCell.TerrainTypeIndex; types.y = beginCell.TerrainTypeIndex; types.z = beginCell.TerrainTypeIndex; TriangulateBoundaryTriangle(right, color3, begin, color1, boundary, boundaryColor, types); if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { TriangulateBoundaryTriangle(left, color2, right, color3, boundary, boundaryColor, types); } else { terrain.AddTriangleUnperturbed(HexMetrics_Script.Perturb(left), HexMetrics_Script.Perturb(right), boundary); //Search for Rand Error terrain.AddTriangleColor(color2, color3, boundaryColor); terrain.AddTriangleTerrainTypes(types); } }
public void AddWall(EdgeVertices near, HexCell_Script nearCell, EdgeVertices far, HexCell_Script farCell, bool hasRiver, bool hasRoad) { if (nearCell.Walled != farCell.Walled && !nearCell.IsUnderwater && !farCell.IsUnderwater && nearCell.GetEdgeType(farCell) != HexEdgeType.Cliff) { AddWallSegment(near.v1, far.v1, near.v2, far.v2); if (hasRiver || hasRoad) { AddWallCap(near.v2, far.v2); AddWallCap(far.v4, near.v4); } else { AddWallSegment(near.v2, far.v2, near.v3, far.v3); AddWallSegment(near.v3, far.v3, near.v4, far.v4); } AddWallSegment(near.v4, far.v4, near.v5, far.v5); } }
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 TriangulateCorner(Vector3 bottom, HexCell_Script bottomCell, Vector3 left, HexCell_Script leftCell, Vector3 right, HexCell_Script rightCell) { HexEdgeType leftEdgeType = bottomCell.GetEdgeType(leftCell); HexEdgeType rightEdgeType = bottomCell.GetEdgeType(rightCell); if (leftEdgeType == HexEdgeType.Slope) { if (rightEdgeType == HexEdgeType.Slope) { TriangulateCornerTerraces(bottom, bottomCell, left, leftCell, right, rightCell); return; } else if (rightEdgeType == HexEdgeType.Flat) { TriangulateCornerTerraces(left, leftCell, right, rightCell, bottom, bottomCell); } else { TriangulateCornerTerracesCliff(bottom, bottomCell, left, leftCell, right, rightCell); } } else if (rightEdgeType == HexEdgeType.Slope) { if (leftEdgeType == HexEdgeType.Flat) { TriangulateCornerTerraces(right, rightCell, bottom, bottomCell, left, leftCell); } else { TriangulateCornerCliffTerraces(bottom, bottomCell, left, leftCell, right, rightCell); } } else if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) { if (leftCell.Elevation < rightCell.Elevation) { TriangulateCornerCliffTerraces(right, rightCell, bottom, bottomCell, left, leftCell); } else { TriangulateCornerTerracesCliff(left, leftCell, right, rightCell, bottom, bottomCell); } return; } else { terrain.AddTriangle(bottom, left, right); //Search for Rand Error terrain.AddTriangleColor(color1, color2, color3); Vector3 types; types.x = bottomCell.TerrainTypeIndex; types.y = leftCell.TerrainTypeIndex; types.z = rightCell.TerrainTypeIndex; terrain.AddTriangleTerrainTypes(types); } features.AddWall(bottom, bottomCell, left, leftCell, right, rightCell); }
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); } }