public virtual bool PlaceAtLocation(IntVector2 location)
	{
		Location = location;
		if (location != null)
		{
			hexCell = GridManager.instance.GetHexCell(location);
			if (hexCell != null)
			{
				transform.position = hexCell.transform.position;
				hexCell.placedPlaceable = this;
				return true;
			}
		}
		else
		{
			if (hexCell != null)
			{
				if (hexCell.placedPlaceable == this)
				{
					hexCell.placedPlaceable = null;
				}
				hexCell = null;
			}
		}
		return false;
	}
	public override bool PlaceAtLocation(IntVector2 location)
	{
		
		Location = location;
		if (location != null)
		{
			hexCell     = GridManager.instance.GetHexCell(location);
			leftBelow   = GridManager.instance.GetHexCell(location+HexMetrics.GetGridOffset(HexMetrics.Direction.LeftDown));
			centerBelow = GridManager.instance.GetHexCell(location+HexMetrics.GetGridOffset(HexMetrics.Direction.Down));
			rightBelow  = GridManager.instance.GetHexCell(location+HexMetrics.GetGridOffset(HexMetrics.Direction.RightDown));
			
			if (hexCell != null && leftBelow != null && centerBelow != null && rightBelow != null)
			{
				foreach (HexCell hc in new HexCell [4] {hexCell, leftBelow, centerBelow, rightBelow})
				{
					if (hc.placedPlaceable != null)
					{
						return false;
					}
				}
				
				transform.position = hexCell.transform.position;
				foreach (HexCell hc in new HexCell [4] {hexCell, leftBelow, centerBelow, rightBelow})
				{
					hc.placedPlaceable = this;
				}
				
				return true;
			}
		}
		else
		{
			if (hexCell != null && leftBelow != null && centerBelow != null && rightBelow != null)
			{
//				if (hexCell.placedPlaceable == this)
//				{
//					hexCell.placedPlaceable = null;
//				}
				foreach (HexCell hc in new HexCell [4] {hexCell, leftBelow, centerBelow, rightBelow})
				{
					if (hc.placedPlaceable == this)
					{
						hc.placedPlaceable = null;
					}
				}
				hexCell = null;
				leftBelow = null;
				centerBelow = null;
				rightBelow = null;
			}
			
		}
		
		return false;
	}
Beispiel #3
0
    private void Triangulate(HexCell cell) {
        Vector3 center = cell.transform.localPosition;

        for(int i = 0; i < 6; i++) {
            AddTriangle(
                center, 
                center + HexMetrics.corners[i], 
                center + HexMetrics.corners[i + 1]
            );
        }
    }
	protected void PlaceOverLocation(IntVector2 location)
	{
		if (location != null)
		{
			hexCell = GridManager.instance.GetHexCell(location);
			if (hexCell)
			{
				transform.position = hexCell.transform.position;
			}
		}
	}
Beispiel #5
0
    public void TriangulateCells(HexCell[] cells) {
        _hexMesh.Clear();
        _vertices.Clear();
        _tris.Clear();

        for(int i = 0; i < cells.Length; i++) {
            Triangulate(cells[i]);
        }

        _hexMesh.vertices = _vertices.ToArray();
        _hexMesh.triangles = _tris.ToArray();
        _hexMesh.RecalculateNormals();
    }
Beispiel #6
0
 public void Triangulate(HexCell[] cells)
 {
     hexMesh.Clear();
     vertices.Clear();
     colors.Clear();
     triangles.Clear();
     for (int i = 0; i < cells.Length; i++) {
         Triangulate(cells[i]);
     }
     hexMesh.vertices = vertices.ToArray();
     hexMesh.colors = colors.ToArray();
     hexMesh.triangles = triangles.ToArray();
     hexMesh.RecalculateNormals();
     meshCollider.sharedMesh = hexMesh;
 }
Beispiel #7
0
 public bool IsValidDestination(HexCell cell)
 {
     return(cell.TerrainType != HexTerrainTypes.Lake && !cell.Unit);
 }
    public static Optional <Path> FindPath(MapPawn mapPawn)
    {
        HexCell start = mapPawn.Location;
        HexCell dest  = mapPawn.Destination;

        // For node n, cameFrom[n] is the node immediately preceding it on the cheapest path from start
        // to n currently known.
        Dictionary <HexCell, PathNode> cameFrom = MapPool <HexCell, PathNode> .GLGet();

        // For node n, gScore[n] is the cost of the cheapest path from start to n currently known.
        Dictionary <HexCell, int> gScore = MapPool <HexCell, int> .GLGet();

        gScore[start] = 0;

        // For node n, fScore[n] = gScore[n] + h(n). fScore[n] represents our current best guess as to
        // how short a path from start to finish can be if it goes through n.
        int startFScore = Heuristic(start, dest);

        // The set of discovered nodes that may need to be (re-)expanded.
        PriorityQueue <HexCell> openSet = ObjectPool <PriorityQueue <HexCell> > .GLGet();

        openSet.Add(start, startFScore);

        // The set of nodes for which a shortest path has already been found
        HashSet <HexCell> closedSet = HashSetPool <HexCell> .GLGet();

        while (!openSet.IsEmpty())
        {
            HexCell current = (HexCell)openSet.Poll();  // Explicit cast because we know this can never be null
            if (current == dest)
            {
                ObjectPool <PriorityQueue <HexCell> > .GLRestore(openSet);

                MapPool <HexCell, int> .GLRestore(gScore);

                HashSetPool <HexCell> .GLRestore(closedSet);

                return(ReconstructPath(cameFrom, current));
            }

            closedSet.Add(current);

            for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)
            {
                HexCell neighbor = current.GetNeighbor(dir);

                if (neighbor == null || closedSet.Contains(neighbor))
                {
                    continue;                                                   // Dont waste time with already evaluated nodes
                }
                if (!mapPawn.CanTransverse(current, neighbor, dir))
                {
                    continue;                                                   // We cannot go there
                }
                int transversalCost  = mapPawn.TransversalCost(current, neighbor);
                int tentative_gScore = gScore[current] + transversalCost;

                int neighbor_gScore = gScore.ContainsKey(neighbor) ? gScore[neighbor] : int.MaxValue;
                if (tentative_gScore < neighbor_gScore)
                {
                    cameFrom[neighbor] = new PathNode(current, transversalCost);
                    gScore[neighbor]   = tentative_gScore;
                    int fScore = tentative_gScore + Heuristic(neighbor, dest);

                    if (!openSet.Update(neighbor, fScore))
                    {
                        openSet.Add(neighbor, fScore);
                    }
                }
            }
        }

        // Open set is empty but goal was never reached
        ObjectPool <PriorityQueue <HexCell> > .GLRestore(openSet);

        MapPool <HexCell, PathNode> .GLRestore(cameFrom);

        MapPool <HexCell, int> .GLRestore(gScore);

        HashSetPool <HexCell> .GLRestore(closedSet);

        return(null);
    }
 private static int Heuristic(HexCell current, HexCell destination)
 {
     return(current.Coordinates.DistanceTo(destination.Coordinates));
 }
    void TriangulateCornerCliffTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell)
    {
        float b = 1f / (leftCell.Elevation - beginCell.Elevation);

        if (b < 0.0f)
        {
            b = -b;
        }
        Vector3 boundary      = Vector3.Lerp(HexMetrics.Perturb(begin), HexMetrics.Perturb(left), b);
        Color   boundaryColor = Color.Lerp(beginCell.Color, leftCell.Color, b);

        TriangulateBoundaryTriangle(right, rightCell, begin, beginCell, boundary, boundaryColor);

        if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope)
        {
            TriangulateBoundaryTriangle(left, leftCell, right, rightCell, boundary, boundaryColor);
        }
        else
        {
            terrain.AddTriangleUnperturbed(HexMetrics.Perturb(left), HexMetrics.Perturb(right), boundary);
            terrain.AddTriangleColor(leftCell.Color, rightCell.Color, boundaryColor);
        }
    }
    void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1)
    {
        HexCell neighbor = cell.GetNeighbor(direction);

        if (neighbor == null)
        {
            return;
        }

        Vector3 bridge = HexMetrics.GetBridge(direction);

        bridge.y = neighbor.Position.y - cell.Position.y;
        EdgeVertices e2 = new EdgeVertices(e1.v1 + bridge, e1.v5 + bridge);

        if (cell.HasRiverThroughEdge(direction))
        {
            e2.v3.y = neighbor.StreamBedY;
            TriangulateRiverQuad(
                e1.v2, e1.v4, e2.v2, e2.v4,
                cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f,
                cell.HasIncomingRiver && cell.IncomingRiver == direction
                );
        }

        if (cell.GetEdgeType(direction) == HexEdgeType.Slope)
        {
            TriangulateEdgeTerraces(
                e1, cell, e2, neighbor, cell.HasRoadThroughEdge(direction)
                );
        }
        else
        {
            TriangulateEdgeStrip(
                e1, cell.Color, e2, neighbor.Color,
                cell.HasRoadThroughEdge(direction)
                );
        }

        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());

        if (direction <= HexDirection.E && nextNeighbor != null)
        {
            Vector3 v5 = e1.v5 + HexMetrics.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
                    );
            }
        }
    }
 void EditCell(HexCell cell)
 {
     cell.color     = activeColor;
     cell.Elevation = activeElevation;
     hexGrid.Refresh();
 }
Beispiel #13
0
    void TriangulateConnection(
		HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2
	)
    {
        HexCell neighbor = cell.GetNeighbor(direction);
        if (neighbor == null) {
            return;
        }

        Vector3 bridge = HexMetrics.GetBridge(direction);
        Vector3 v3 = v1 + bridge;
        Vector3 v4 = v2 + bridge;
        v3.y = v4.y = neighbor.Elevation * HexMetrics.elevationStep;

        if (cell.GetEdgeType(direction) == HexEdgeType.Slope) {
            TriangulateEdgeTerraces(v1, v2, cell, v3, v4, neighbor);
        }
        else {
            AddQuad(v1, v2, v3, v4);
            AddQuadColor(cell.color, neighbor.color);
        }

        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());
        if (direction <= HexDirection.E && nextNeighbor != null) {
            Vector3 v5 = v2 + HexMetrics.GetBridge(direction.Next());
            v5.y = nextNeighbor.Elevation * HexMetrics.elevationStep;

            if (cell.Elevation <= neighbor.Elevation) {
                if (cell.Elevation <= nextNeighbor.Elevation) {
                    TriangulateCorner(v2, cell, v4, neighbor, v5, nextNeighbor);
                }
                else {
                    TriangulateCorner(v5, nextNeighbor, v2, cell, v4, neighbor);
                }
            }
            else if (neighbor.Elevation <= nextNeighbor.Elevation) {
                TriangulateCorner(v4, neighbor, v5, nextNeighbor, v2, cell);
            }
            else {
                TriangulateCorner(v5, nextNeighbor, v2, cell, v4, neighbor);
            }
        }
    }
Beispiel #14
0
 /// <summary>
 /// Edits the cell.
 /// </summary>
 /// <param name="cell">Cell.</param>
 void EditCell(HexCell cell)
 {
     cell.Color    = activeColor;
     cell.moveCost = cell.level [newIndex];
 }
Beispiel #15
0
    void TriangulateEdgeTerraces(
		Vector3 beginLeft, Vector3 beginRight, HexCell beginCell,
		Vector3 endLeft, Vector3 endRight, HexCell endCell
	)
    {
        Vector3 v3 = HexMetrics.TerraceLerp(beginLeft, endLeft, 1);
        Vector3 v4 = HexMetrics.TerraceLerp(beginRight, endRight, 1);
        Color c2 = HexMetrics.TerraceLerp(beginCell.color, endCell.color, 1);

        AddQuad(beginLeft, beginRight, v3, v4);
        AddQuadColor(beginCell.color, c2);

        for (int i = 2; i < HexMetrics.terraceSteps; i++) {
            Vector3 v1 = v3;
            Vector3 v2 = v4;
            Color c1 = c2;
            v3 = HexMetrics.TerraceLerp(beginLeft, endLeft, i);
            v4 = HexMetrics.TerraceLerp(beginRight, endRight, i);
            c2 = HexMetrics.TerraceLerp(beginCell.color, endCell.color, i);
            AddQuad(v1, v2, v3, v4);
            AddQuadColor(c1, c2);
        }

        AddQuad(v3, v4, endLeft, endRight);
        AddQuadColor(c2, endCell.color);
    }
Beispiel #16
0
    void TriangulateCornerTerracesCliff(
		Vector3 begin, HexCell beginCell,
		Vector3 left, HexCell leftCell,
		Vector3 right, HexCell rightCell
	)
    {
        float b = 1f / (rightCell.Elevation - beginCell.Elevation);
        if (b < 0) {
            b = -b;
        }
        Vector3 boundary = Vector3.Lerp(begin, right, b);
        Color boundaryColor = Color.Lerp(beginCell.color, rightCell.color, b);

        TriangulateBoundaryTriangle(
            begin, beginCell, left, leftCell, boundary, boundaryColor
        );

        if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope) {
            TriangulateBoundaryTriangle(
                left, leftCell, right, rightCell, boundary, boundaryColor
            );
        }
        else {
            AddTriangle(left, right, boundary);
            AddTriangleColor(leftCell.color, rightCell.color, boundaryColor);
        }
    }
Beispiel #17
0
    void TriangulateCornerTerraces(
		Vector3 begin, HexCell beginCell,
		Vector3 left, HexCell leftCell,
		Vector3 right, HexCell rightCell
	)
    {
        Vector3 v3 = HexMetrics.TerraceLerp(begin, left, 1);
        Vector3 v4 = HexMetrics.TerraceLerp(begin, right, 1);
        Color c3 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, 1);
        Color c4 = HexMetrics.TerraceLerp(beginCell.color, rightCell.color, 1);

        AddTriangle(begin, v3, v4);
        AddTriangleColor(beginCell.color, c3, c4);

        for (int i = 2; i < HexMetrics.terraceSteps; i++) {
            Vector3 v1 = v3;
            Vector3 v2 = v4;
            Color c1 = c3;
            Color c2 = c4;
            v3 = HexMetrics.TerraceLerp(begin, left, i);
            v4 = HexMetrics.TerraceLerp(begin, right, i);
            c3 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, i);
            c4 = HexMetrics.TerraceLerp(beginCell.color, rightCell.color, i);
            AddQuad(v1, v2, v3, v4);
            AddQuadColor(c1, c2, c3, c4);
        }

        AddQuad(v3, v4, left, right);
        AddQuadColor(c3, c4, leftCell.color, rightCell.color);
    }
Beispiel #18
0
    void TriangulateCorner(
		Vector3 bottom, HexCell bottomCell,
		Vector3 left, HexCell leftCell,
		Vector3 right, HexCell 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
                );
            }
            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
                );
            }
        }
        else {
            AddTriangle(bottom, left, right);
            AddTriangleColor(bottomCell.color, leftCell.color, rightCell.color);
        }
    }
Beispiel #19
0
 public void SetNeighbor(HexDirection direction, HexCell cell)
 {
     neighbors[(int)direction] = cell;
     cell.neighbors[(int)direction.Opposite()] = this;
 }
    public bool AskCreateUnit(UrbanCity city, int actorInfoId)
    {
        HexCell cellCenter = GameRoomManager.Instance.HexmapHelper.GetCell(city.CellIndex);// 城市中心地块

        return(AskCreateUnit(cellCenter, actorInfoId));
    }
Beispiel #21
0
 bool IsValidRiverDestination(HexCell neighbor)
 {
     return(neighbor && (
                elevation >= neighbor.elevation || waterLevel == neighbor.elevation
                ));
 }
Beispiel #22
0
    void TriangulateBoundaryTriangle(
		Vector3 begin, HexCell beginCell,
		Vector3 left, HexCell leftCell,
		Vector3 boundary, Color boundaryColor
	)
    {
        Vector3 v2 = HexMetrics.TerraceLerp(begin, left, 1);
        Color c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, 1);

        AddTriangle(begin, v2, boundary);
        AddTriangleColor(beginCell.color, c2, boundaryColor);

        for (int i = 2; i < HexMetrics.terraceSteps; i++) {
            Vector3 v1 = v2;
            Color c1 = c2;
            v2 = HexMetrics.TerraceLerp(begin, left, i);
            c2 = HexMetrics.TerraceLerp(beginCell.color, leftCell.color, i);
            AddTriangle(v1, v2, boundary);
            AddTriangleColor(c1, c2, boundaryColor);
        }

        AddTriangle(v2, left, boundary);
        AddTriangleColor(c2, leftCell.color, boundaryColor);
    }
Beispiel #23
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;
        Vector3 v1 = center + HexMetrics.GetFirstSolidCorner(direction);
        Vector3 v2 = center + HexMetrics.GetSecondSolidCorner(direction);

        AddTriangle(center, v1, v2);
        AddTriangleColor(cell.color);

        if (direction <= HexDirection.SE) {
            TriangulateConnection(direction, cell, v1, v2);
        }
    }
Beispiel #24
0
    public void EvolveClimate(HexCell hexCell)
    {
        ClimateData climateData = m_climateData[hexCell.CellIndex];

        if (hexCell.IsUnderwater)
        {
            climateData.moisture = 1f;
            climateData.clouds  += Evaporation;
        }
        else
        {
            float evaporation = climateData.moisture * EvaporationFactor;
            climateData.moisture -= evaporation;
            climateData.clouds   += evaporation;
        }

        float precipitation = climateData.clouds * PrecipitationFactor;

        climateData.clouds   -= precipitation;
        climateData.moisture += precipitation;

        float cloudMaximum = 1f - hexCell.ViewElevation / (ElevationMaximum + 1f);

        if (climateData.clouds > cloudMaximum)
        {
            climateData.moisture += climateData.clouds - cloudMaximum;
            climateData.clouds    = cloudMaximum;
        }

        float perCellFactor = (1f / 6f);

        HexDirection mainDispersalDirection = WindDirection.Opposite();

        float cloudDispersion = climateData.clouds * (1f / (5f + WindStrength));
        float runoff          = climateData.moisture * RunoffFactor * perCellFactor;
        float seepage         = climateData.moisture * SeepageFactor * perCellFactor;

        for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)
        {
            HexCell neighbor = hexCell.GetNeighbour(dir);
            if (neighbor == null)
            {
                continue;
            }

            ClimateData neighbourClimateData = m_nextClimateData[neighbor.CellIndex];
            if (dir == mainDispersalDirection)
            {
                neighbourClimateData.clouds += cloudDispersion * WindStrength;
            }
            else
            {
                neighbourClimateData.clouds += cloudDispersion;
            }

            int elevationDelta = neighbor.ViewElevation - hexCell.ViewElevation;
            if (elevationDelta < 0)
            {
                climateData.moisture          -= runoff;
                neighbourClimateData.moisture += runoff;
            }
            else if (elevationDelta == 0)
            {
                climateData.moisture          -= seepage;
                neighbourClimateData.moisture += seepage;
            }

            m_nextClimateData[neighbor.CellIndex] = neighbourClimateData;
        }

        ClimateData nextCellClimateData = m_nextClimateData[hexCell.CellIndex];

        nextCellClimateData.moisture += climateData.moisture;
        nextCellClimateData.moisture  = Mathf.Min(1f, nextCellClimateData.moisture);

        m_nextClimateData[hexCell.CellIndex] = nextCellClimateData;
        m_climateData[hexCell.CellIndex]     = new ClimateData();
    }
Beispiel #25
0
 public void UpdateRoot(Pawn pawn, HexCell oldCell, HexCell newCell)
 {
     pawn.currentCell = newCell;
     newCell.pawn     = pawn;
     oldCell.pawn     = null;
 }
Beispiel #26
0
    public void CreateRivers()
    {
        List <HexCell> riverOrigins = ListPool <HexCell> .Get();

        foreach (HexCell hexCell in HexGrid.GetHexCells())
        {
            if (hexCell.IsUnderwater)
            {
                continue;
            }

            ClimateData climateData = m_climateData[hexCell.CellIndex];
            float       data        = climateData.moisture * (float)(hexCell.Elevation - WaterLevel) / (ElevationMaximum - WaterLevel);
            if (data > 0.75f)
            {
                riverOrigins.Add(hexCell);
                riverOrigins.Add(hexCell);
            }
            if (data > 0.5f)
            {
                riverOrigins.Add(hexCell);
            }
            if (data > 0.25f)
            {
                riverOrigins.Add(hexCell);
            }
        }

        int riverBudget = Mathf.RoundToInt(m_numLandCells * RiverPercentage * 0.01f);

        while (riverBudget > 0 && riverOrigins.Count > 0)
        {
            int     index  = Random.Range(0, riverOrigins.Count);
            HexCell origin = riverOrigins[index];
            riverOrigins.RemoveAt(index);
            if (!origin.HasRiver)
            {
                bool isValidOrigin = true;
                for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)
                {
                    HexCell neighbour = origin.GetNeighbour(dir);
                    if (neighbour != null && (neighbour.HasRiver || neighbour.IsUnderwater))
                    {
                        isValidOrigin = false;
                        break;
                    }
                }

                if (isValidOrigin)
                {
                    riverBudget -= CreateRiver(origin);
                }
            }
        }

        if (riverBudget > 0)
        {
            Debug.LogWarning("Failed to use up river budget");
        }


        ListPool <HexCell> .Return(riverOrigins);
    }
    void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        bool    hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool    previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous());
        bool    nextHasRiver       = cell.HasRiverThroughEdge(direction.Next());
        Vector2 interpolators      = GetRoadInterpolators(direction, cell);
        Vector3 roadCenter         = center;

        if (cell.HasRiverBeginOrEnd)
        {
            roadCenter += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f);
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite())
        {
            Vector3 corner;
            if (previousHasRiver)
            {
                if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Next()))
                {
                    return;
                }
                corner = HexMetrics.GetSecondSolidCorner(direction);
            }
            else
            {
                if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Previous()))
                {
                    return;
                }
                corner = HexMetrics.GetFirstSolidCorner(direction);
            }
            roadCenter += corner * 0.5f;
            center     += corner * 0.25f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())
        {
            roadCenter -= HexMetrics.GetSecondCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())
        {
            roadCenter -= HexMetrics.GetFirstCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (previousHasRiver && nextHasRiver)
        {
            if (!hasRoadThroughEdge)
            {
                return;
            }
            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.innerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
        }
        else
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }
            if (!cell.HasRoadThroughEdge(middle) && !cell.HasRoadThroughEdge(middle.Previous()) && !cell.HasRoadThroughEdge(middle.Next()))
            {
                return;
            }
            roadCenter += HexMetrics.GetSolidEdgeMiddle(middle) * 0.25f;
        }

        Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Beispiel #28
0
    public int CreateRiver(HexCell riverOrigin)
    {
        int          length                = 0;
        HexCell      hexCell               = riverOrigin;
        HexDirection direction             = HexDirection.NE;
        int          minNeighbourElevation = int.MaxValue;

        while (!hexCell.IsUnderwater)
        {
            m_flowDirections.Clear();

            for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)
            {
                HexCell neighbour = hexCell.GetNeighbour(dir);
                if (neighbour == null)
                {
                    continue;
                }
                if (neighbour.Elevation < minNeighbourElevation)
                {
                    minNeighbourElevation = neighbour.Elevation;
                }

                if (neighbour == riverOrigin || neighbour.HasIncomingRiver)
                {
                    continue;
                }

                int delta = neighbour.Elevation - hexCell.Elevation;
                if (delta > 0)
                {
                    continue;
                }

                if (neighbour.HasOutgoingRiver)
                {
                    hexCell.SetOutgoingRiver(dir);
                    return(length);
                }

                if (length == 1 || (dir != direction.Next2() && dir != direction.Previous2()))
                {
                    m_flowDirections.Add(dir);
                }


                // weight dowhills
                if (delta < 0)
                {
                    m_flowDirections.Add(dir);
                    m_flowDirections.Add(dir);
                    m_flowDirections.Add(dir);
                }

                m_flowDirections.Add(dir);
            }

            if (m_flowDirections.Count == 0)
            {
                if (length == 1)
                {
                    return(0);
                }

                if (minNeighbourElevation >= hexCell.Elevation)
                {
                    hexCell.WaterLevel = minNeighbourElevation;
                    if (minNeighbourElevation == hexCell.Elevation)
                    {
                        hexCell.Elevation = minNeighbourElevation - 1;
                    }
                }
                break;
            }


            direction = m_flowDirections[Random.Range(0, m_flowDirections.Count)];
            hexCell.SetOutgoingRiver(direction);
            length += 1;

            if (minNeighbourElevation >= hexCell.Elevation && Random.value < ExtraLakeProability)
            {
                hexCell.WaterLevel = hexCell.Elevation;
                hexCell.Elevation--;
            }

            hexCell = hexCell.GetNeighbour(direction);
        }

        return(length);
    }
    void TriangulateCorner(
        Vector3 bottom, HexCell bottomCell,
        Vector3 left, HexCell leftCell,
        Vector3 right, HexCell 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
                    );
            }
            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
                    );
            }
        }
        else
        {
            terrain.AddTriangle(bottom, left, right);
            terrain.AddTriangleColor(
                bottomCell.Color, leftCell.Color, rightCell.Color
                );
        }
    }
Beispiel #30
0
    void Update()
    {
        if (!EventSystem.current.IsPointerOverGameObject())
        {
            if (HexGameController.myTurn && !myUnit.isTraveling)
            {
                DoPathfinding();
                if (Input.GetMouseButtonDown(1))
                {
                    DoMove();
                }
            }
            else
            {
                currentCell = null;
            }
        }

        if (Input.GetKeyDown("space"))
        {
            myUnit.Jump();
            photonView.RPC("GetJump", RpcTarget.Others, true);
        }

        // center camera to myUnit position
        if (Input.GetKeyDown(KeyCode.C))
        {
            HexMapCamera.SetPosition(myUnit.Location);
        }

        // toggle camera following
        if (Input.GetKeyDown(KeyCode.V))
        {
            following = !following;
            if (following)
            {
                HexMapCamera.SetPosition(myUnit.Location);
                switchToFollowing = true;
            }
        }

        // move camera
        if (switchToFollowing)
        {
            if (HexMapCamera.GetLocalPosition() == myUnit.transform.localPosition)
            {
                switchToFollowing = false;
            }
        }
        else if (following)
        {
            HexMapCamera.SetPosition(myUnit.transform.localPosition, true);
        }
        else
        {
            HexMapCamera.Move();
        }

        // networking
        if (otherUnit)
        {
            if (UnitInfo.newPath)
            {
                DoMove(UnitInfo.Path);
                UnitInfo.newPath = false;
            }

            if (UnitInfo.Jump)
            {
                otherUnit.Jump();
                UnitInfo.Jump = false;
            }
        }
    }
Beispiel #31
0
    public bool CanSpawnAt(Hex hex)
    {
        HexCell cell = cells.ContainsKey(hex.ToString()) ? cells[hex.ToString()] : null;

        return(cell && !cell.occupied);
    }
 public void RefreshTerrain(HexCell cell)
 {
     cellTextureData[cell.Index].a = (byte)cell.TerrainTypeIndex;
     enabled = true;
 }
 public PathNode(HexCell location, int costTo)
 {
     this.location = location;
     this.costTo   = costTo;
 }
 public void RefreshVisibility(HexCell cell)
 {
     cellTextureData[cell.Index].r = cell.IsVisible ? (byte)255 : (byte)0;
     enabled = true;
 }
Beispiel #35
0
 void EditCell(HexCell cell)
 {
     if (cell)
     {
         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.RemoveRiver();
         }
         if (roadMode == OptionalToggle.No)
         {
             cell.RemoveRoads();
         }
         if (walledMode != OptionalToggle.Ignore)
         {
             cell.Walled = walledMode == OptionalToggle.Yes;
         }
         if (isDrag)
         {
             HexCell otherCell = cell.GetNeighbor(dragDirection.Opposite());
             if (otherCell)
             {
                 if (riverMode == OptionalToggle.Yes)
                 {
                     otherCell.SetOutgoingRiver(dragDirection);
                 }
                 if (roadMode == OptionalToggle.Yes)
                 {
                     otherCell.AddRoad(dragDirection);
                 }
             }
         }
     }
 }
Beispiel #36
0
 public virtual void Use(HexCell cell)
 {
     throw new NotImplementedException();
 }
Beispiel #37
0
 public Boolean CanAttack(HexCell targetCell)
 {
     return(_availableMoves.ContainsKey(targetCell) && _availableMoves[targetCell].CanAttack);
 }
Beispiel #38
0
    /// <summary>
    /// Instantiates the Hex prefabs, assigning them their positions in relation to each other.
    /// Assigns the neighbors of each hex in relation to each side (E.g. NE,SW, W, E, SE, NW).
    /// Also responsible for attaching a Text label on top of each Hex displaying its location.
    /// Adds the cell to its appropriate chunk
    /// </summary>
    /// <param name="x"> X Column value for the Hex </param>
    /// <param name="z"> Z Column value for the Hex </param>
    /// <param name="i"> Index for cells </param>
    void CreateCell(int x, int z, int i)
    {
        Vector3 position;

        position.x = (x + z * 0.5f - z / 2) * HexMetrics.innerDiameter;
        position.y = 0f;
        position.z = z * (HexMetrics.outerRadius * 1.5f);

        HexCell cell = cells[i] = Instantiate <HexCell>(cellPrefab);

        cell.transform.localPosition = position;
        cell.coordinates             = HexCoordinates.FromOffsetCoordinates(x, z);
        cell.Index       = i;
        cell.ColumnIndex = x / HexMetrics.chunkSizeX;
        cell.ShaderData  = cellShaderData;

        if (wrapping)
        {
            cell.Explorable = z > 0 && z < cellCountZ - 1;
        }
        else
        {
            cell.Explorable =
                x > 0 && z > 0 && x < cellCountX - 1 && z < cellCountZ - 1;
        }

        if (x > 0)
        {
            cell.SetNeighbor(HexDirection.W, cells[i - 1]);
            if (wrapping && x == cellCountX - 1)
            {
                cell.SetNeighbor(HexDirection.E, cells[i - x]);
            }
        }
        if (z > 0)
        {
            if ((z & 1) == 0)
            {
                cell.SetNeighbor(HexDirection.SE, cells[i - cellCountX]);
                if (x > 0)
                {
                    cell.SetNeighbor(HexDirection.SW, cells[i - cellCountX - 1]);
                }
                else if (wrapping)
                {
                    cell.SetNeighbor(HexDirection.SW, cells[i - 1]);
                }
            }
            else
            {
                cell.SetNeighbor(HexDirection.SW, cells[i - cellCountX]);
                if (x < cellCountX - 1)
                {
                    cell.SetNeighbor(HexDirection.SE, cells[i - cellCountX + 1]);
                }
                else if (wrapping)
                {
                    cell.SetNeighbor(
                        HexDirection.SE, cells[i - cellCountX * 2 + 1]
                        );
                }
            }
        }

        Text label = Instantiate <Text>(cellLabelPrefab);

        label.rectTransform.anchoredPosition =
            new Vector2(position.x, position.z);
        cell.uiRect = label.rectTransform;

        cell.Elevation = 0;

        AddCellToChunk(x, z, cell);
    }
Beispiel #39
0
 public HexEdgeType GetEdgeType(HexCell otherCell)
 {
     return(HexMetrics.GetEdgeType(
                elevation, otherCell.elevation
                ));
 }
Beispiel #40
0
    /// <summary>
    /// Used for finding the most optimal path to reaching an end point by comparing distances and hazards that lead to that point.
    /// It weights each hex based on it distance value and its position being closer to the end point.
    /// The hexes with the most progress in these categories get assessed first to minimize the amount of loops of the method.
    /// Once it finds the end hex, it works backwards with hexes remembering which way they came to work to the origin point.
    /// Edit. Now assigns how many turns it would take to get there based on distance a unit can move.
    /// </summary>
    /// <param name="fromCell"> Origin hex </param>
    /// <param name="toCell"> Destination hex </param>
    /// <returns> Creates path towards end destination </returns>
    bool Search(HexCell fromCell, HexCell toCell, HexUnit unit)
    {
        int speed = unit.Speed;

        searchFrontierPhase += 2;

        if (searchFrontier == null)
        {
            searchFrontier = new HexCellPriorityQueue();
        }
        else
        {
            searchFrontier.Clear();
        }

        fromCell.SearchPhase = searchFrontierPhase;
        fromCell.Distance    = 0;

        searchFrontier.Enqueue(fromCell);
        while (searchFrontier.Count > 0)
        {
            HexCell current = searchFrontier.Dequeue();
            current.SearchPhase += 1;

            if (current == toCell)
            {
                return(true);
            }

            int currentTurn = (current.Distance - 1) / speed;

            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbour = current.GetNeighbor(d);

                if (neighbour == null || neighbour.SearchPhase > searchFrontierPhase)
                {
                    continue;
                }

                if (!unit.IsValidDestination(neighbour))
                {
                    continue;
                }

                int moveCost = unit.GetMoveCost(current, neighbour, d);

                if (moveCost < 0)
                {
                    continue;
                }

                int distance = current.Distance + moveCost;
                int turn     = (distance - 1) / speed;

                if (turn > currentTurn)
                {
                    distance = turn * speed + moveCost;
                }

                if (neighbour.SearchPhase < searchFrontierPhase)
                {
                    neighbour.Distance        = distance;
                    neighbour.SearchPhase     = searchFrontierPhase;
                    neighbour.PathFrom        = current;
                    neighbour.SearchHeuristic = neighbour.coordinates.DistanceTo(toCell.coordinates);
                    searchFrontier.Enqueue(neighbour);
                }
                else if (distance < neighbour.Distance)
                {
                    int oldPriority = neighbour.SearchPriority;
                    neighbour.Distance = distance;

                    neighbour.PathFrom = current;
                    searchFrontier.Change(neighbour, oldPriority);
                }
            }
        }
        return(false);
    }
Beispiel #41
0
 // TODO: ekki nota ?
 public void ChangeMoveCost(HexCell cell)
 {
     cell.moveCost = cell.level[cell.index];
 }
 public void AddWall(Vector3 c1, HexCell cell1, Vector3 c2, HexCell cell2, Vector3 c3, HexCell cell3)
 {
     if (cell1.Walled)
     {
         if (cell2.Walled)
         {
             if (!cell3.Walled)
             {
                 AddWallSegment(c3, cell3, c1, cell1, c2, cell2);
             }
         }
         else if (cell3.Walled)
         {
             AddWallSegment(c2, cell2, c3, cell3, c1, cell1);
         }
         else
         {
             AddWallSegment(c1, cell1, c2, cell2, c3, cell3);
         }
     }
     else if (cell2.Walled)
     {
         if (cell3.Walled)
         {
             AddWallSegment(c1, cell1, c2, cell2, c3, cell3);
         }
         else
         {
             AddWallSegment(c2, cell2, c3, cell3, c1, cell1);
         }
     }
     else if (cell3.Walled)
     {
         AddWallSegment(c3, cell3, c1, cell1, c2, cell2);
     }
 }
Beispiel #43
0
    /// <summary>
    /// Gets all hex cells in a given range from a specified point.
    /// </summary>
    /// <param name="fromCell"> Starting cell </param>
    /// <param name="range"> How many hexes from the origin it will search in a circle </param>
    /// <returns> List of Hex cells in a radius from the center hex </returns>
    List <HexCell> GetVisibleCells(HexCell fromCell, int range)
    {
        List <HexCell> visibleCells = ListPool <HexCell> .Get();

        searchFrontierPhase += 2;

        if (searchFrontier == null)
        {
            searchFrontier = new HexCellPriorityQueue();
        }
        else
        {
            searchFrontier.Clear();
        }

        range += fromCell.ViewElevation;
        fromCell.SearchPhase = searchFrontierPhase;
        fromCell.Distance    = 0;

        HexCoordinates fromCoordinates = fromCell.coordinates;

        searchFrontier.Enqueue(fromCell);
        while (searchFrontier.Count > 0)
        {
            HexCell current = searchFrontier.Dequeue();
            current.SearchPhase += 1;

            visibleCells.Add(current);

            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbour = current.GetNeighbor(d);

                if (neighbour == null || neighbour.SearchPhase > searchFrontierPhase || !neighbour.Explorable)
                {
                    continue;
                }

                int distance = current.Distance + 1;

                if (distance + neighbour.ViewElevation > range || distance > fromCoordinates.DistanceTo(neighbour.coordinates))
                {
                    continue;
                }

                if (neighbour.SearchPhase < searchFrontierPhase)
                {
                    neighbour.Distance        = distance;
                    neighbour.SearchPhase     = searchFrontierPhase;
                    neighbour.SearchHeuristic = 0;
                    searchFrontier.Enqueue(neighbour);
                }
                else if (distance < neighbour.Distance)
                {
                    int oldPriority = neighbour.SearchPriority;
                    neighbour.Distance = distance;

                    searchFrontier.Change(neighbour, oldPriority);
                }
            }
        }
        return(visibleCells);
    }
Beispiel #44
0
 void Triangulate(HexCell cell)
 {
     for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) {
         Triangulate(d, cell);
     }
 }