Ejemplo n.º 1
0
    public WaterTriangulationData TriangulateHexWaterShoreEdge(
        Hex source,
        Hex neighbor,
        Dictionary <HexDirections, Hex> neighbors,
        HexDirections direction,
        HexRiverData riverData,
        WaterTriangulationData triangulationData,
        float hexOuterRadius,
        int wrapSize
        )
    {
        if (source.IsUnderwater)
        {
            if (
                !neighbor.IsUnderwater
                )
            {
                Vector3 center2 = neighbor.Position;

                float hexInnerRadius =
                    HexagonPoint.OuterToInnerRadius(hexOuterRadius);

                float hexInnerDiameter = hexInnerRadius * 2f;

                //            / | y
                //           /  |
                //           |  |
                //source x/z |  | target
                //           |  |
                //           \  |
                //            \ | y

                Vector3 waterShoreHexIndices;

                waterShoreHexIndices.x     =
                    waterShoreHexIndices.z = source.Index;

                waterShoreHexIndices.y = neighbor.Index;

                TriangulateWaterShore(
                    source,
                    neighbor,
                    waterShoreHexIndices,
                    direction,
                    neighbors,
                    riverData,
                    triangulationData.waterSurfaceCenter,
                    hexOuterRadius,
                    wrapSize,
                    this,
                    triangulationData.sourceWaterEdge,
                    triangulationData.neighborWaterEdge,
                    hexInnerDiameter
                    );
            }
        }

        return(triangulationData);
    }
Ejemplo n.º 2
0
    private IEnumerator LookAt(
        Vector3 point,
        float hexOuterRadius,
        HexMap hexMap
        )
    {
        float innerRadius   = HexagonPoint.OuterToInnerRadius(hexOuterRadius);
        float innerDiameter = innerRadius * 2f;

        if (hexMap.IsWrapping)
        {
            float xDistance = point.x - transform.localPosition.x;
            if (xDistance < -innerRadius * hexMap.WrapSize)
            {
                point.x += innerDiameter * hexMap.WrapSize;
            }
            else if (xDistance > innerRadius * hexMap.WrapSize)
            {
                point.x -= innerDiameter * hexMap.WrapSize;
            }
        }

        point.y = transform.localPosition.y;
        Quaternion fromRotation = transform.localRotation;
        Quaternion toRotation   =
            Quaternion.LookRotation(point - transform.localPosition);

        float angle = Quaternion.Angle(fromRotation, toRotation);

        if (angle > 0f)
        {
            float speed = _rotationSpeed / angle;

            for (
                float t = Time.deltaTime * speed;
                t < 1f;
                t += Time.deltaTime * speed
                )
            {
                transform.localRotation =
                    Quaternion.Slerp(fromRotation, toRotation, t);
                yield return(null);
            }

            transform.LookAt(point);
            _orientation = transform.localRotation.eulerAngles.y;
        }
    }
Ejemplo n.º 3
0
    private Vector3 ClampPosition(
        HexMap grid,
        Vector3 position,
        float hexOuterRadius
        )
    {
// Get inner diameter of a given hex.
        float innerDiameter =
            HexagonPoint.OuterToInnerRadius(hexOuterRadius) * 2f;

        float xMax =
            (grid.HexOffsetColumns - 0.5f) * innerDiameter;

        position.x = Mathf.Clamp(position.x, 0f, xMax);

        float zMax =
            (grid.HexOffsetRows - 1) * (1.5f * hexOuterRadius);

        position.z = Mathf.Clamp(position.z, 0f, zMax);

        return(position);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Get a CubeVector corresponding to a Vector3.
    /// </summary>
    /// <param name="vector3">
    /// The specified Vector3, where the x and z coordinates are
    /// considered to be the corresponding x and z coordinates of
    /// the resulting cube vector.
    /// </param>
    /// <param name="hexOuterRadius">
    /// The distance from the center of a hex to one of its corners.
    /// </param>
    /// <param name="wrapOffsetX">
    /// The offset required to wrap cube coordinates around the x
    /// axis. Should be set to the width of the bounds of the plane
    /// which the coordinate is located on.
    /// </param>
    /// <returns>
    /// A cube vector corresponding to the position of the Vector3.
    /// </returns>
    public static CubeVector FromVector3(
        Vector3 vector3,
        float hexOuterRadius,
        int wrapOffsetX
        )
    {
        float innerDiameter =
            HexagonPoint.OuterToInnerRadius(hexOuterRadius) * 2f;

        // Divide X by the horizontal width of a hexagon.
        float x = vector3.x / innerDiameter;

        // The y axis is just the inverse of the x axis.
        float y = -x;

        //Shift every two rows one unit to the left.
        float offset = vector3.z / (hexOuterRadius * 3f);

        x -= offset;
        y -= offset;

        int integerX = Mathf.RoundToInt(x);
        int integerY = Mathf.RoundToInt(y);

        //  X + Y + Z = 0->
        //  X + Z = -Y ->
        //  (X + Z) / -1 = -Y / -1 ->
        //  -X - Z = Y
        int integerZ = Mathf.RoundToInt(-x - y);

        if (integerX + integerY + integerZ != 0)
        {
            // As a coordinate gets further away from the center,
            // the likelihood of it producing a rounding error
            // increases. Therefore, find the largest rounding
            // delta.

            float deltaX = Mathf.Abs(x - integerX);
            float deltaY = Mathf.Abs(y - integerY);
            float deltaZ = Mathf.Abs(-x - y - integerZ);

            // If X has the largest rounding delta, reconstruct X
            // from Y and Z
            if (deltaX > deltaY && deltaX > deltaZ)
            {
                integerX = -integerY - integerZ;
            }

            //If Z has the largest rounding delta, reconstruct Z
            // from X and Y
            else if (deltaZ > deltaY)
            {
                integerZ = -integerX - integerY;
            }
        }

        return(new CubeVector(
                   integerX,
                   integerZ,
                   wrapOffsetX
                   ));
    }
Ejemplo n.º 5
0
// TODO: This should not be the responsibilty of this class. Should
//       probably be located in the HexMap.
//    public int GetMoveCost
//    (
//        Hex fromHex,
//       Hex toHex,
//        HexDirection direction
//    ) {
//        int moveCost;
//
//        ElevationEdgeTypes edgeType = fromHex.GetEdgeType(toHex);
//        if (edgeType == ElevationEdgeTypes.Cliff) {
//            return -1;
//        }
//
//        if (fromHex.HasRoadThroughEdge(direction)) {
//            moveCost = 1;
//        }
//        else if (fromHex.HasWalls != toHex.HasWalls) {
//            return -1;
//        }
//        else {
//            moveCost = edgeType == ElevationEdgeTypes.Flat ? 5 : 10;
//            moveCost +=
//                toHex.UrbanLevel + toHex.FarmLevel + toHex.PlantLevel;
//        }
//
//        return moveCost;
//    }

// ~~ private
    private IEnumerator TravelPath(float hexOuterRadius, HexMap hexMap)
    {
        float innerDiameter =
            HexagonPoint.OuterToInnerRadius(hexOuterRadius) * 2f;
        Vector3 pointA, pointB, pointC = _pathToTravel[0].Position;

        yield return(LookAt(
                         _pathToTravel[1].Position,
                         hexOuterRadius,
                         hexMap
                         ));

        if (!_currentDestination)
        {
            _currentDestination = _pathToTravel[0];
        }
// TODO: This is a circular dependency and needs to be fixed.
//        Grid.DecreaseVisibility(_currentDestination, VisionRange);

        int currentColumn = _currentDestination.ColumnIndex;

        float t = Time.deltaTime * _travelSpeed;

        for (int i = 1; i < _pathToTravel.Count; i++)
        {
            _currentDestination = _pathToTravel[i];

// Start or previous hex midpoint.
            pointA = pointC;

// Current hex position.
            pointB = _pathToTravel[i - 1].Position;

            int nextColumn = _currentDestination.ColumnIndex;
            if (currentColumn != nextColumn)
            {
                if (nextColumn < currentColumn - 1)
                {
                    pointA.x -= innerDiameter * hexMap.WrapSize;
                    pointB.x -= innerDiameter * hexMap.WrapSize;
                }
                else if (nextColumn > currentColumn + 1)
                {
                    pointA.x += innerDiameter * hexMap.WrapSize;
                    pointB.x += innerDiameter * hexMap.WrapSize;
                }
//                Grid.MakeChildOfColumn(transform, nextColumn);
                currentColumn = nextColumn;
            }

            pointC = (pointB + _currentDestination.Position) * 0.5f;
// TODO: This is a circular dependency and needs to be fixed.
//            Grid.IncreaseVisibility(_pathToTravel[i], VisionRange);

            for (; t < 1f; t += Time.deltaTime * _travelSpeed)
            {
                transform.StandOn(
                    Bezier.GetQuadradicPoint(pointA, pointB, pointC, t)
                    );

                Vector3 direction = Bezier.GetDerivative(pointA, pointB, pointC, t);

                // Lock y rotation.
                direction.y = 0f;

                transform.localRotation = Quaternion.LookRotation(direction);
                yield return(null);
            }

            _currentDestination = null;

// TODO: This is a circular dependency and needs to be fixed.
//            Grid.DecreaseVisibility(_pathToTravel[i], _visionRange);

/* Subtract 1 from each time "segment" to carry over the remaining
 * time into the next loop, which will prevent stuttering if the
 * frame rate is low.
 */
            t -= 1f;
        }

        pointA = pointC;

/* Can simply use destination, as the unit is at the
 * last hex before the end of the path.
 */
        pointB = Location.Position;

        pointC = pointB;

// TODO: This is a circular dependency and needs to be fixed.
//        Grid.IncreaseVisibility(_location, _visionRange);

        for (; t < 1f; t += Time.deltaTime * _travelSpeed)
        {
            transform.StandOn(
                Bezier.GetQuadradicPoint(pointA, pointB, pointC, t)
                );
            Vector3 direction = Bezier.GetDerivative(pointA, pointB, pointC, t);
            direction.y             = 0f;
            transform.localRotation = Quaternion.LookRotation(direction);
            yield return(null);
        }

/* Because the amount of movement depends on t, the unit may be short of its
 * destination by a small amount. When the unit has completed its animation,
 * snap it into the correct position by assigning its position explicitly.
 */
        transform.StandOn(_location.Position);
        _orientation = transform.localRotation.eulerAngles.y;
    }
Ejemplo n.º 6
0
    private WaterTriangulationData GetWaterData(
        Hex source,
        Hex neighbor,
        WaterTriangulationData waterTriData,
        HexDirections direction,
        float hexOuterRadius,
        int wrapSize
        )
    {
        waterTriData.waterSurfaceCenter   = source.Position;
        waterTriData.waterSurfaceCenter.y = source.WaterSurfaceY;

        waterTriData.sourceWaterEdge = new EdgeVertices(
            waterTriData.waterSurfaceCenter +
            HexagonPoint.GetFirstWaterCorner(
                direction,
                hexOuterRadius
                ),
            waterTriData.waterSurfaceCenter +
            HexagonPoint.GetSecondWaterCorner(
                direction,
                hexOuterRadius
                )
            );

        Vector3 neighborCenter = neighbor.Position;

        float hexInnerRadius =
            HexagonPoint.OuterToInnerRadius(hexOuterRadius);

        float hexInnerDiameter = hexInnerRadius * 2f;

// TODO: This will not work once the column index is removed from
//       Hex class.
// If the neighbor outside the wrap boundaries, adjust accordingly.
        if (neighbor.ColumnIndex < source.ColumnIndex - 1)
        {
            neighborCenter.x +=
                wrapSize * hexInnerDiameter;
        }
        else if (neighbor.ColumnIndex > source.ColumnIndex + 1)
        {
            neighborCenter.x -=
                wrapSize * hexInnerDiameter;
        }

        neighborCenter.y = waterTriData.waterSurfaceCenter.y;

        waterTriData.neighborWaterEdge = new EdgeVertices(
            neighborCenter + HexagonPoint.GetSecondSolidCorner(
                direction.Opposite(),
                hexOuterRadius
                ),
            neighborCenter + HexagonPoint.GetFirstSolidCorner(
                direction.Opposite(),
                hexOuterRadius
                )
            );

        return(waterTriData);
    }
Ejemplo n.º 7
0
/// <summary>
/// Create a hex representing the data
/// </summary>
/// <param name="offsetX">
/// An x coordinate in the offset coordinate system.
/// </param>
/// <param name="offsetZ">
/// A z coordiante in the offset coordinate system.
/// </param>
/// <param name="rowMajorIndex">
/// The row-major index of the hex.
/// </param>
/// <param name="hexOuterRadius">
/// The outer radius of the hex.
/// </param>
/// <param name="hexGrid">
/// The hex grid to the hex to as an element.
/// </param>
/// <returns>
/// A hex, instantiated at world space coordinates cooresponding
/// to offsetX and offsetZ and assigned to the specified hex grid at
/// offsetX and offsetZ.
/// </returns>
    private Hex CreateHexFromOffsetCoordinates(
        int offsetX,
        int offsetZ,
        int rowMajorIndex,
        float hexOuterRadius,
        HexGrid <Hex> hexGrid
        )
    {
// metrics.
        float innerDiameter =
            HexagonPoint.OuterToInnerRadius(hexOuterRadius) * 2f;

// Create the Hexes object and monobehaviour.
        Hex result = Hex.Instantiate(offsetX, offsetZ, WrapSize);

// Set the Hexes transform.
        result.transform.localPosition = CoordinateToLocalPosition(
            offsetX,
            offsetZ,
            innerDiameter,
            hexOuterRadius
            );

        result.name = "Hex " + result.CubeCoordinates;

        result.Index       = rowMajorIndex;
        result.ColumnIndex = offsetX / HexMeshConstants.CHUNK_SIZE_X;
        result.ShaderData  = _hexShaderData;

// If wrapping is enabled, hex is not explorable if the hex is on the
// top or bottom border.
        if (IsWrapping)
        {
            result.IsExplorable = offsetZ > 0 && offsetZ < HexOffsetColumns - 1;
        }
// If wrapping is disabled, hex is not explorable if the hex is on
// any border.
        else
        {
            result.IsExplorable =
                offsetX > 0 &&
                offsetZ > 0 &&
                offsetX < HexOffsetColumns - 1 &&
                offsetZ < HexOffsetRows - 1;
        }

// THIS IS NOW HANDLED BY MAPPING THE DENSEARRAY TO AN ADJACENCY GRAP
//
// At the beginning of each row, x == 0. Therefore, if x is greater than
// 0, set the east/west connection of the hex between the current hex
// and the previous hex in the array.
//        if (x > 0) {
//            result.SetNeighborPair(HexDirection.West, result[i - 1]);
//
//            if (_wrapping && x == _hexCountX - 1) {
//                result.SetNeighborPair(HexDirection.East, result[i - x]);
//            }
//        }
//
// At the first row, z == 0. The first row has no southern neighbors. Therefore
//
//        if (z > 0)
//        {
// Use the bitwise operator to mask off all but the first bit. If the result is 0,
// the number is even:
//      11 (3) & 1(1) == 1
//       ^
//       |
//       AND only compares the length of the smallest binary sequence
//       |
//      10 (2) & 1(1) == 0
//
// Because all hexes in even rows have a southeast neighbor, they can be connected.
//
//            if ((z & 1) == 0)
//            {
//                result.SetNeighborPair(HexDirection.SouthEast, result[i - _hexCountX]);
//
// All even hexess except for the first hex in each row have a southwest neighbor.
//                if (x > 0)
//                {
//                    result.SetNeighborPair(HexDirection.SouthWest, result[i - _hexCountX - 1]);
//                }
//                else if (_wrapping)
//                {
//                    result.SetNeighborPair(HexDireFtion.SouthWest, result[i - 1]);
//                }
//            }
//            else
//            {
//                result.SetNeighborPair(HexDirection.SouthWest, result[i - _hexCountX]);
//
//                //All odd hexess except the last hex in each row have a southeast neighbor
//                if (x < _hexCountX - 1)
//                {
//                    result.SetNeighborPair(HexDirection.SouthEast, result[i - _hexCountX + 1]);
//                }
//                else if (_wrapping)
//                {
//                    result.SetNeighborPair(HexDirection.SouthEast, result[i - _hexCountX * 2 + 1]);
//                }
//            }
//        }

// TODO: Presentation considerations should be moved to a separate class.
        Text label = new GameObject().AddComponent <Text>();

        label.rectTransform.anchoredPosition =
            new Vector2(
                result.transform.localPosition.x,
                result.transform.localPosition.z
                );

        result.uiRect = label.rectTransform;
        result.SetElevation(
            0,
            hexOuterRadius,
            hexGrid.WrapSize
            );

        return(result);
    }