//takes a hex and a direction and returns the two vectors of the positions of the
    //corners that make up the border between the hex and its neighbor in the given direction
    //in clockwise order
    private (Vector3, Vector3) GetCorners(HexMap.DIRECTION d, Hex h)
    {
        Vector3 pos = hexMap.GetGOFromHex(h).transform.position;

        //vectors to get us the corner from the hex transform position
        Vector3 n  = pos + new Vector3(0, y, r);   //north
        Vector3 ne = pos + new Vector3(w, y, z);   //north east
        Vector3 se = pos + new Vector3(w, y, -z);  //south east
        Vector3 s  = pos + new Vector3(0, y, -r);  //south
        Vector3 sw = pos + new Vector3(-w, y, -z); //south west
        Vector3 nw = pos + new Vector3(-w, y, z);  //north west

        switch (d)
        {
        case HexMap.DIRECTION.NORTHEAST:
            return(n, ne);

        case HexMap.DIRECTION.EAST:
            return(ne, se);

        case HexMap.DIRECTION.SOUTHEAST:
            return(se, s);

        case HexMap.DIRECTION.SOUTHWEST:
            return(s, sw);

        case HexMap.DIRECTION.WEST:
            return(sw, nw);

        case HexMap.DIRECTION.NORTHWEST:
            return(nw, n);
        }
        return(Vector3.zero, Vector3.zero);
    }
Exemple #2
0
    public Hex GetNeighbor(HexMap.DIRECTION dir)
    {
        switch (dir)
        {
        case HexMap.DIRECTION.NORTHEAST:
            return(hexMap.GetHex(this.Q, this.R + 1));

        case HexMap.DIRECTION.EAST:
            return(hexMap.GetHex(this.Q + 1, this.R));

        case HexMap.DIRECTION.SOUTHEAST:
            return(hexMap.GetHex(this.Q + 1, this.R - 1));

        case HexMap.DIRECTION.SOUTHWEST:
            return(hexMap.GetHex(this.Q, this.R - 1));

        case HexMap.DIRECTION.WEST:
            return(hexMap.GetHex(this.Q - 1, this.R));

        case HexMap.DIRECTION.NORTHWEST:
            return(hexMap.GetHex(this.Q - 1, this.R + 1));
        }
        return(null);
    }
    private HexMap.DIRECTION GetOppositeDirection(HexMap.DIRECTION dir)
    {
        switch (dir)
        {
        case HexMap.DIRECTION.WEST:
            return(HexMap.DIRECTION.EAST);

        case HexMap.DIRECTION.NORTHWEST:
            return(HexMap.DIRECTION.SOUTHEAST);

        case HexMap.DIRECTION.NORTHEAST:
            return(HexMap.DIRECTION.SOUTHWEST);

        case HexMap.DIRECTION.EAST:
            return(HexMap.DIRECTION.WEST);

        case HexMap.DIRECTION.SOUTHEAST:
            return(HexMap.DIRECTION.NORTHWEST);

        case HexMap.DIRECTION.SOUTHWEST:
            return(HexMap.DIRECTION.NORTHEAST);
        }
        return(0);
    }
    public void UpdateCityBorders(City city, GameObject cityGO, Dictionary <City,
                                                                            GameObject> cityToGOMap, Dictionary <GameObject, City> goToCityMap)
    {
        List <Blob> blobs = new List <Blob>();

        //make sure each city has a line renderer and reset them all
        //create a new blob for each city
        List <City> cities = cityToGOMap.Keys.ToList <City>();

        foreach (City c in cities)
        {
            if (!borderLineRenderers.ContainsKey(c))
            {
                LineRenderer borderLineRenderer;
                borderLineRenderer     = GetNewLineRenderer(c);
                borderLineRenderers[c] = borderLineRenderer;
            }
            else
            {
                borderLineRenderers[c].enabled = false;
            }

            blobs.Add(new Blob(c, new HashSet <Hex>(c.GetHexes())));
        }

        List <Blob> newBlobs = new List <Blob>();

        bool[] merged = new bool[blobs.Count];
        for (int i = 0; i < blobs.Count; i++)
        {
            if (merged[i])
            {
                continue;
            }
            newBlobs.Add(blobs[i]);
            bool somethingMerged;
            do
            {
                somethingMerged = false;
                for (int j = i + 1; j < blobs.Count; j++)
                {
                    Blob otherBlob = blobs[j];
                    if (blobs[i].hexes.Overlaps(otherBlob.hexes) && !merged[j])
                    {
                        merged[j]       = true;
                        somethingMerged = true;
                        blobs[i].hexes.UnionWith(otherBlob.hexes);
                    }
                }
            } while (somethingMerged);
        }
        blobs = newBlobs;

        foreach (Blob blob in blobs)
        {
            Debug.Log("Drawing border for blob around city: " + blob.city.name);
            //hexes contained in this blob
            HashSet <Hex> hexes = blob.hexes;
            //hexes we've visited so far
            HashSet <Hex> visitedHexes = new HashSet <Hex>();

            //need a hashset of positions for fast set operations and array because order matters
            List <Vector3>    positions = new List <Vector3>();
            HashSet <Vector3> posSet    = new HashSet <Vector3>();

            //find a hex on the edge of the blob.
            Hex currHex = hexes.First <Hex>();
            while (hexes.Contains(currHex.GetNeighbor(HexMap.DIRECTION.NORTHEAST)))
            {
                currHex = currHex.GetNeighbor(HexMap.DIRECTION.NORTHEAST);
            }

            Debug.Log("Found a hex on the edge of the blob: " + currHex.CoordsString());

            //until we get back to the starting hex
            HexMap.DIRECTION dir      = HexMap.DIRECTION.SOUTHEAST;
            bool             finished = false;
            while (!finished)
            {
                //start one edge clockwise of the direction we came from
                dir = GetOppositeDirection(dir);
                dir = GetNextClockwiseDirection(dir);
                //search clockwise checking if each neighbor is in the blob
                //if not, add the vertices for that edge to the list
                //if so, move to that hex
                while (!hexes.Contains(currHex.GetNeighbor(dir)))
                {
                    //set a line position on the corners that make the border
                    (Vector3, Vector3)corners = GetCorners(dir, currHex);

                    //round values to we don't miss duplicates due to floating point error
                    corners.Item1.x = (float)Math.Round((Decimal)corners.Item1.x, 3, MidpointRounding.AwayFromZero);
                    corners.Item1.y = (float)Math.Round((Decimal)corners.Item1.y, 3, MidpointRounding.AwayFromZero);
                    corners.Item1.z = (float)Math.Round((Decimal)corners.Item1.z, 3, MidpointRounding.AwayFromZero);

                    corners.Item2.x = (float)Math.Round((Decimal)corners.Item2.x, 3, MidpointRounding.AwayFromZero);
                    corners.Item2.y = (float)Math.Round((Decimal)corners.Item2.y, 3, MidpointRounding.AwayFromZero);
                    corners.Item2.z = (float)Math.Round((Decimal)corners.Item2.z, 3, MidpointRounding.AwayFromZero);

                    bool containsCorner1 = posSet.Contains(corners.Item1);
                    bool containsCorner2 = posSet.Contains(corners.Item2);
                    //check for exit condition
                    if (containsCorner1 && containsCorner2 && visitedHexes.Contains(currHex))
                    {
                        finished = true;
                        break;
                    }

                    //otherwise make sure we don't add duplicates
                    if (!containsCorner1)
                    {
                        positions.Add(corners.Item1);
                        posSet.Add(corners.Item1);
                    }

                    if (!containsCorner2)
                    {
                        positions.Add(corners.Item2);
                        posSet.Add(corners.Item2);
                    }

                    dir = GetNextClockwiseDirection(dir);
                    Debug.Log("Checking direction: " + dir.ToString());
                }

                visitedHexes.Add(currHex);
                currHex = currHex.GetNeighbor(dir);
            }

            //draw border for this blob
            LineRenderer borderLineRenderer = borderLineRenderers[blob.city];
            borderLineRenderer.positionCount = positions.Count;
            borderLineRenderer.loop          = true;
            borderLineRenderer.SetPositions(positions.ToArray());
            borderLineRenderer.enabled = true;
        }
    }