示例#1
0
文件: HexGrid.cs 项目: jimu/pbem001
    /// <summary>
    ///   Instantiates a HexCell in cells[i] at x*10, z*10. Parents the HexCell GameObject to this HexGrid
    /// </summary>
    /// <param name="x">x-grid position</param>
    /// <param name="z">z-grid position</param>
    /// <param name="i">index into cells[]</param>
    void CreateCell(int x, int z, int i)
    {
        Vector3 position = GridToPosition(x, z);
        //position.x = x * 10f;     // grid positioning
        //position.z = z * 10f;

        /*
         * position.x = (x + z / 2f - z / 2 ) * (HexMetrics.innerRadius * 2f);
         * position.y = 0f;
         * position.z = z * (HexMetrics.outerRadius * 1.5f);
         */
        HexCell cell = cells[i] = Instantiate <HexCell>(cellPrefab);

        cell.transform.SetParent(transform, false);
        cell.transform.localPosition = position;
        cell.coordinates             = HexCoordinates.FromOffsetCoordinates(x, z);

        string         rivetString   = cell.coordinates.ToRivetsString();
        bool           inRangeOfBCPC = rivetString == "1103" || rivetString == "1104";
        HexCoordinates bcpc          = HexCoordinates.FromRivets(11, 5);
        int            distance      = bcpc.Distance(cell.coordinates);

        // Debug.Log($"{bcpc} ({bcpc.ToRivetsString()}) to {cell.coordinates} ({cell.coordinates.ToRivetsString()}): {distance}");
        inRangeOfBCPC = distance <= 5;                                 // todo
        cell.color    = inRangeOfBCPC ? highlightColor : defaultColor; // new Color(1f, 0.5f, 0.5f);// Color.green;

        Text label = Instantiate <Text>(cellLabelPrefab);

        label.rectTransform.SetParent(gridCanvas.transform, false);
        label.rectTransform.anchoredPosition = new Vector2(position.x + label_offset_x, position.z);
        //label.text = cell.coordinates.ToStringOnSeparateLines();  // $"{x}\n{z}";
        label.text = cell.coordinates.ToRivetsString(); // + "\n" + cell.coordinates.ToString();
    }
示例#2
0
    public void TryGetTowerLocation(Vector3 position, Tower tower)
    {
        HexCoordinates hex = TryGetHexCoordinateFromWorldPosition(position, out bool success);

        if (success)
        {
            HexInfo info = cellInfo[hex];
            success = !info.Occupied && info.Reachable;
            if (success)
            {
                HexInfo closestHex = info;

                List <HexInfo> available =
                    hex.GetStraightLinesOfLength(2).Where(h => cellInfo.ContainsKey(h) && cellInfo[h].Filled).Select(n => cellInfo[n]).ToList();

                int   minHexDistance      = 100;
                float minPhysicalDistance = 100;
                foreach (HexInfo i in available)
                {
                    int dist = HexCoordinates.Distance(hex, i.Coordinates);
                    if (dist < minHexDistance)
                    {
                        float pDist = Vector2.Distance(i.PhysicalCoordinates, position);
                        minHexDistance      = dist;
                        minPhysicalDistance = pDist;
                        closestHex          = i;
                    }
                    else if (dist == minHexDistance)
                    {
                        float pDist = Vector2.Distance(i.PhysicalCoordinates, position);
                        if (pDist < minPhysicalDistance)
                        {
                            minPhysicalDistance = pDist;
                            closestHex          = i;
                        }
                    }
                }

                success = minHexDistance < 100;
                if (success)
                {
                    Vector3 diff   = closestHex.PhysicalCoordinates - info.PhysicalCoordinates;
                    Vector3 posRot = info.PhysicalCoordinates + (diff / 2f) + (0.5f * (minHexDistance - 1) * InnerRadius) * diff.normalized;
                    posRot.z = Vector2.SignedAngle(Vector2.down, diff);

                    tower.Height = minHexDistance;
                    tower.gameObject.SetActive(true);
                    tower.transform.position = new Vector3(posRot.x, posRot.y, -0.5f);
                    tower.transform.rotation = Quaternion.Euler(0, 0, posRot.z);
                    tower.GridPosition       = info.Coordinates;
                }
            }
        }

        if (!success)
        {
            tower.gameObject.SetActive(false);
        }
    }
示例#3
0
    internal static List<HexCoordinates> GetAllPathableTiles(EntityMapping entityMap, TileListBase tileMap, HexCoordinates source, IEntityMovement movement, IMapCollisionDetection map)
    {
        List<HexCoordinates> ret = new List<HexCoordinates>();
        IEntityMovement Move = movement;
        int MoveRange = movement.MovementRange;
        List<HexNode> closedset = new List<HexNode>(); //nodes already examined
        List<HexNode> openset = new List<HexNode>(); //nodes that still can be examined

        HexNode thing = new HexNode(source, source, null); 

        thing.H = HexCoordinates.Distance(source, source); //dont really care 'bout H
        openset.Add(thing);

        while (openset.Count > 0)
        {
            HexNode current = openset[0];
            openset.Remove(current);
            closedset.Add(current);
            if (current.G >= MoveRange) { continue; } //can't go any further from this location
            List<HexCoordinates> neighbors = map.AdjacentMoveSpaces(entityMap, tileMap, current.Coords, movement);
            for (int i = 0; i < neighbors.Count; i++)
            {
                bool found = false;
                HexCoordinates NeighborCoords = neighbors[i];
                for (int j = 0; j < closedset.Count; j++)
                {
                    if (closedset[j].Coords == NeighborCoords)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //node was found in closedset, so dont do anything
                for (int j = 0; j < openset.Count; j++)
                {
                    if (openset[j].Coords == NeighborCoords)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //neighbor found in openset, no need to add it again.

                HexNode NewNode = new HexNode(NeighborCoords, source, current); //neighbor is a new node, add it to openset.
                openset.Add(NewNode);
            }
        }
        for(int i=0; i<closedset.Count; i++)
        {
            ret.Add(closedset[i].Coords);
        }
        return ret;
    }
示例#4
0
    public bool ExpandCorridor(ref Stack <TileProperties> remainingTiles, TileProperties affectedTile, HexDirection nextDirection)
    {
        TileProperties nextTile = affectedTile.GetNeighbor(nextDirection);

        if (!nextTile.Tile)
        {
            return(false);
        }
        else if (CanCreateWindOnTile(nextTile))
        {
            nextTile.nextTilesInCorridor.Add(nextDirection);
            nextTile.previousTileInCorridor = nextDirection;
            // nextTile.Tilemap.SetColor(nextTile.Position, Color.red);
            remainingTiles.Push(nextTile);
            nextTile.woOnTile.Add(this);
            corridor.Add(nextTile);

            for (int x = -radius; x <= radius; x++)
            {
                for (int y = -radius; y <= radius; y++)
                {
                    int            z = -y - x;
                    HexCoordinates coordinatesInRange = new HexCoordinates(x, y, z);

                    HexCoordinates other    = nextTile.Coordinates + coordinatesInRange;
                    int            distance = other.Distance(nextTile.Coordinates);
                    if (distance <= radius)
                    {
                        TileProperties neighbor = nextTile.Grid.GetTile(other);
                        if (!neighbor)
                        {
                            continue;
                        }
                        // neighbor.Tilemap.SetColor(neighbor.Position, Color.red);
                        float newWindDryness = -(baseDryness - distance);
                        if (newWindDryness < neighbor.windDryness)
                        {
                            neighbor.humidity   -= neighbor.windDryness;
                            neighbor.windDryness = newWindDryness;
                            neighbor.humidity   += neighbor.windDryness;
                        }
                        neighbor.woAffectingTile.Add(this);
                        tilesAffected.Add(neighbor);
                    }
                }
            }
            return(true);
        }
        return(false);
    }
示例#5
0
    public Vector3 TryGetTowerPlacement(Vector3 position, out bool success, out int distance)
    {
        distance = -1; // just so out doesn't comlpain about not defining direction
        HexCoordinates hex = TryGetHexCoordinateFromWorldPosition(position, out success);

        if (!success)
        {
            return(Vector3.zero);
        }
        HexInfo info = cellInfo[hex];

        success = !info.Filled;
        if (!success)
        {
            return(Vector3.zero);
        }

        HexInfo closestHex  = info;
        float   minDistance = 1001;

        List <HexInfo> available =
            hex.GetStraightLinesOfLength(2).Where(h => cellInfo.ContainsKey(h) && cellInfo[h].Filled).Select(n => cellInfo[n]).ToList();

        foreach (HexInfo i in available)
        {
            float dist = Vector2.Distance(i.PhysicalCoordinates, position);
            if (dist < minDistance)
            {
                minDistance = dist;
                closestHex  = i;
            }
        }

        success = minDistance < 1000;

        distance = HexCoordinates.Distance(hex, closestHex.Coordinates);
        Vector3 diff   = closestHex.PhysicalCoordinates - info.PhysicalCoordinates;
        Vector3 posRot = info.PhysicalCoordinates + (diff / 2f) + (0.5f * (distance - 1) * InnerRadius) * diff.normalized;

        posRot.z = Vector2.SignedAngle(Vector2.down, diff);
        return(posRot);
    }
示例#6
0
 public HexNode(HexCoordinates location, HexCoordinates goal, HexNode parent = null)
 {
     _H = HexCoordinates.Distance(location, goal); //ought to maybe have a list of herustics it consults instead
     _Parent = parent;
     _Coords = location;
 }
示例#7
0
    public static List<HexCoordinates> GetPath(IMapCollisionDetection map, EntityMapping entityMap, TileListBase tileMap, HexCoordinates start, HexCoordinates end, IEntityMovement movement)
    { //tilearray is an array full of tiles, which have cubecoords. start/end are obvious. movementtype influences some of the pathing decisions.
        if (!SanityCheck(map, entityMap, tileMap, start, end, movement)) { return null; }
        List<HexCoordinates> ReturnValue = new List<HexCoordinates>();

        List<HexNode> closedset = new List<HexNode>(); //nodes already examined
        List<HexNode> openset = new List<HexNode>(); //nodes that still can be examined

        /*
        having actual C# lists, instead of just having some kind of linkedlist setup may be a poor choice
        */

        HexNode thing = new HexNode(start, end, null); //location, goal, parent node. starting node has no parent.

        /*
        H is a herustic that is part of determining which node to check first.
        in this case, distance is a distance formula for xyz 
        since the vast majority of time, the closer two points in "real" space, the less nodes exist between them
        this is obviously not always the case (walls exist), but in the majority of cases, it holds true.

        score is H + G, lowest score gets picked from the opennode list
        G value is 1 + parent node's G.
        */
        thing.H = HexCoordinates.Distance(start, end);
        openset.Add(thing);

        while (openset.Count > 0)
        {
            HexNode current = openset[0];
            for (int i = 1; i < openset.Count; i++)
            {
                if (openset[i].Score < current.Score)
                {
                    current = openset[i];
                }
            }

            /*
            The above could, and maybe ought to, be replaced by keeping the openset list sorted after every
            addition, and just popping openset[0].
            I think doing 1-to-n amount of compares for each openset addition
            is more costly than just having a constant n each runthrough
            but maybe it works out so that most openset additions wind up near the front so often
            that it might become noticably faster if openset gets particuarlly large
            but I'm not a computer science guy and its a waste of time to care about stuff like this sometimes
            */

            if (current.Coords.X == end.X && current.Coords.Y == end.Y && current.Coords.Z == end.Z && current.Coords.Depth == end.Depth) //we have reached our goal
            {
                return RebuildPath(current);
            }

            openset.Remove(current); //"pop" current
            closedset.Add(current); //

            //get all tile coords that are adjacent to current
            List<HexCoordinates> neighbors = map.AdjacentMoveSpaces(entityMap, tileMap, current.Coords, movement);
            for (int i = 0; i < neighbors.Count; i++)
            {
                bool found = false;
                HexCoordinates NeighborCoords = neighbors[i];
                for (int j = 0; j < closedset.Count; j++)
                {
                    if (closedset[j].Coords.X == NeighborCoords.X &&
                       closedset[j].Coords.Y == NeighborCoords.Y &&
                       closedset[j].Coords.Z == NeighborCoords.Z &&
                       closedset[j].Coords.Depth == NeighborCoords.Depth)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //node was found in closedset, so dont do anything
                for (int j = 0; j < openset.Count; j++)
                {
                    if (openset[j].Coords.X == NeighborCoords.X &&
                       openset[j].Coords.Y == NeighborCoords.Y &&
                       openset[j].Coords.Z == NeighborCoords.Z &&
                       openset[j].Coords.Depth == NeighborCoords.Depth)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //neighbor found in openset

                HexNode NewNode = new HexNode(NeighborCoords, end, current); //neighbor is a new node, add it to openset.
                openset.Add(NewNode);
            }
        }
        return null; // ran out of currentset before goal was reached. no path is possible.
                     //returning null is kind of dangerous, but it communicates the idea in a self-evident manner, i feel.
    }
示例#8
0
    internal static List<HexCoordinates> GetPathNextTo(EntityMapping entityMap, TileListBase tileMap, IMapCollisionDetection map, HexCoordinates start, HexCoordinates end, IEntityMovement actor)
    {
        List<HexCoordinates> ReturnValue = new List<HexCoordinates>();
        IEntityMovement Move = actor;

        List<HexNode> closedset = new List<HexNode>(); //nodes already examined
        List<HexNode> openset = new List<HexNode>(); //nodes that still can be examined

        HexNode thing = new HexNode(start, end, null); //location, goal, parent node. starting node has no parent.

        thing.H = HexCoordinates.Distance(start, end);
        List<HexCoordinates> AdjacentToEnd = end.GetCoordsWithinDistance(1);
        openset.Add(thing);

        while (openset.Count > 0)
        {
            HexNode current = openset[0];

            if (AdjacentToEnd.Contains(current.Coords)) //we have reached our goal
            {
                return RebuildPath(current);
            }

            openset.Remove(current); //"pop" current
            closedset.Add(current); //

            //get all tile coords that are adjacent to current
            List<HexCoordinates> neighbors = map.AdjacentMoveSpaces(entityMap, tileMap, current.Coords, actor);
            for (int i = 0; i < neighbors.Count; i++)
            {
                bool found = false;
                HexCoordinates NeighborCoords = neighbors[i];
                for (int j = 0; j < closedset.Count; j++)
                {
                    if (closedset[j].Coords == NeighborCoords)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //node was found in closedset, so dont do anything
                for (int j = 0; j < openset.Count; j++)
                {
                    if (openset[j].Coords == NeighborCoords)
                    {
                        found = true;
                        break;
                    }
                }
                if (found) { continue; } //neighbor found in openset, no need to add it again.

                HexNode NewNode = new HexNode(NeighborCoords, end, current); //neighbor is a new node, add it to openset.
                int index = openset.Count;
                for (int j = 0; j < openset.Count; j++)
                {
                    if (NewNode.Score <= openset[j].Score) //newnode has lower or same score, should be inserted before checked node in openset
                    {
                        index = j;
                        break;

                        //doing this sort should improve pathfinding speed...
                    }
                }
                openset.Insert(index, NewNode);
            }
        }
        //UnityEngine.Debug.Log("Invalid path: Could not draw path.");
        return null;
    }