Beispiel #1
0
    public void AIActionStart(Unit _unit)
    {
        int         enemyHero     = (_unit.side + 1) % 2;
        bool        isRangeAttack = _unit.IsRangeAttack;
        List <Unit> enemyList     = BattleManager.instance.units[enemyHero];

        //远程单位,且没有被近身
        if (isRangeAttack)
        {
            Unit target = GetMaxDamageUnit(_unit, enemyList, isRangeAttack);
            UnitActionMgr.order = new Order(OrderType.rangeAttack, _unit, target);
        }
        else
        {
            int         speed      = _unit.GetComponent <Unit>().speed;
            List <Unit> targetList = GetEnemiesWithinRange(_unit, speed + 1);

            Unit target;

            if (targetList.Count > 0)
            {
                //攻击范围内有目标
                target = GetMaxDamageUnit(_unit, targetList, isRangeAttack);
                List <NodeItem> path = AStarManager.FindPath(BattleManager.instance.map,
                                                             _unit.nodeItem, target.nodeItem, false);
                path.RemoveAt(path.Count - 1);

                if (_unit.isWalker)
                {
                    UnitActionMgr.order = new Order(OrderType.attack, _unit, path, target);
                }
                else
                {
                    UnitActionMgr.order = new Order(OrderType.attack, _unit, path[path.Count - 1], target);
                }
            }
            else
            {
                //攻击范围内无目标
                target = GetNearestUnit(_unit, enemyList);
                //且可到达

                List <NodeItem> path = AStarManager.FindPath(BattleManager.instance.map,
                                                             _unit.nodeItem, target.nodeItem, false);

                //去掉移动力之外的部分
                path.RemoveRange(speed, path.Count - speed);

                if (_unit.isWalker)
                {
                    UnitActionMgr.order = new Order(OrderType.move, _unit, path, target);
                }
                else
                {
                    UnitActionMgr.order = new Order(OrderType.move, _unit, path[path.Count - 1], target);
                }
            }
        }
    }
Beispiel #2
0
 public List <Vector2> FindPath(Vector2Int _startLandIdx, Vector2Int _distLandIdx)
 {
     return(ChangeNodeListToPath(AStarManager.FindPath(_startLandIdx, _distLandIdx)));
 }
    public override LinkedList <Node> GeneratePath(int _enemyPosX, int _enemyPosY)
    {
        GridManager       grid    = DungeonManager.Instance.Grids[(int)GridType.Knight];
        LinkedList <Node> retPath = null;

        retPath = AStarManager.FindPath(
            grid.nodes[_enemyPosX, _enemyPosY],
            grid.nodes[GameManager.Instance.Player.PosX, GameManager.Instance.Player.PosY],
            grid);

        if (retPath == null)
        {
            /* Here we try the nearest nodes. If the second AStarPath still returns null,
             * it could be that the enemy piece is completely blocked off.
             * So don't waste more time trying to find a path, just random
             * move to the adjacent blocks.
             */

            // Spiral Nearest when the adjacent tiles are not available. Spiral max radius of 3 tiles.
            int targetPosX = GameManager.Instance.Player.PosX;
            int targetPosY = GameManager.Instance.Player.PosY;

            bool emptyTileFound = false;
            int  increment      = 1;
            int  iMax           = 1;
            while ((iMax - 1) < 5)
            {
                for (int y = 0; y < iMax; y++)
                {
                    targetPosY += increment;
                    if (DungeonManager.Instance.IsCellEmpty(targetPosX, targetPosY))
                    {
                        retPath = AStarManager.FindPath(
                            grid.nodes[_enemyPosX, _enemyPosY],
                            grid.nodes[targetPosX, targetPosY],
                            grid);
                        emptyTileFound = true;
                        break;
                    }
                }

                for (int x = 0; x < iMax; x++)
                {
                    targetPosX += increment;
                    if (DungeonManager.Instance.IsCellEmpty(targetPosX, targetPosY))
                    {
                        retPath = AStarManager.FindPath(
                            grid.nodes[_enemyPosX, _enemyPosY],
                            grid.nodes[targetPosX, targetPosY],
                            grid);
                        emptyTileFound = true;
                        break;
                    }
                }

                if (emptyTileFound)
                {
                    break;
                }

                iMax++;
                increment *= -1;
            }

            // If the path is still null (maybe enemy is blocked off by structure), just random anyhow position to the adjacent tiles.
            if (retPath == null)
            {
                LinkedList <Node> neighbours = grid.nodes[_enemyPosX, _enemyPosY].neighbours;
                for (LinkedListNode <Node> curNode = neighbours.First; curNode != null; curNode = curNode.Next)
                {
                    if (DungeonManager.Instance.IsCellEmpty(curNode.Value.PosX, curNode.Value.PosY))
                    {
                        retPath = new LinkedList <Node>();
                        retPath.AddFirst(grid.nodes[curNode.Value.PosX, curNode.Value.PosY]);
                        retPath.AddFirst(grid.nodes[_enemyPosX, _enemyPosY]);
                        break;
                    }
                }
            }
        }

        // If STILL null (can't move all; all neighbours blocked), then no choice, return null and don't move.

        return(retPath);
    }
    public override LinkedList <Node> GeneratePath(int _enemyPosX, int _enemyPosY)
    {
        GridManager       grid    = DungeonManager.Instance.Grids[(int)GridType.King];
        LinkedList <Node> retPath = null;

        // For king only, because the possibilities are a LOT more, so best to check if player is blocked off
        // For example, when it is completely surrounded by enemies, king cannot reach it.
        // So better to just skip the first AStar search because it is so expensive.

        // Check if there are any empty adjacent nodes to the player.
        LinkedList <Node> playerNodeNeighbours = grid.nodes[GameManager.Instance.Player.PosX, GameManager.Instance.Player.PosY].neighbours;

        for (LinkedListNode <Node> curNode = playerNodeNeighbours.First; curNode != null; curNode = curNode.Next)
        {
            // If it is one of the surrounding pieces, just directly generate the path.
            // Need this check, otherwise one of the pieces will move out of formation,
            // as it detects that the player is surrounded, but does not realize that it is one of the 8 surrounding pieces.
            if (curNode.Value.PosX == _enemyPosX && curNode.Value.PosY == _enemyPosY)
            {
                retPath = AStarManager.FindPath(
                    grid.nodes[_enemyPosX, _enemyPosY],
                    grid.nodes[GameManager.Instance.Player.PosX, GameManager.Instance.Player.PosY],
                    grid);
                break;
            }

            if (DungeonManager.Instance.IsCellEmpty(curNode.Value.PosX, curNode.Value.PosY))
            {
                retPath = AStarManager.FindPath(
                    grid.nodes[_enemyPosX, _enemyPosY],
                    grid.nodes[GameManager.Instance.Player.PosX, GameManager.Instance.Player.PosY],
                    grid);
                break;
            }
        }

        if (retPath == null)
        {
            /* Here we try the nearest nodes. If the second AStarPath still returns null,
             * it could be that the enemy piece is completely blocked off.
             * So don't waste more time trying to find a path, just random
             * move to the adjacent blocks.
             */

            // Spiral Nearest when the adjacent tiles are not available. Spiral max radius of 3 tiles.
            int targetPosX = GameManager.Instance.Player.PosX;
            int targetPosY = GameManager.Instance.Player.PosY;

            bool emptyTileFound = false;
            int  increment      = 1;
            int  iMax           = 1;
            while ((iMax - 1) < 5)
            {
                for (int y = 0; y < iMax; y++)
                {
                    targetPosY += increment;
                    if (DungeonManager.Instance.IsCellEmpty(targetPosX, targetPosY))
                    {
                        retPath = AStarManager.FindPath(
                            grid.nodes[_enemyPosX, _enemyPosY],
                            grid.nodes[targetPosX, targetPosY],
                            grid);
                        emptyTileFound = true;
                        break;
                    }
                }

                for (int x = 0; x < iMax; x++)
                {
                    targetPosX += increment;
                    if (DungeonManager.Instance.IsCellEmpty(targetPosX, targetPosY))
                    {
                        retPath = AStarManager.FindPath(
                            grid.nodes[_enemyPosX, _enemyPosY],
                            grid.nodes[targetPosX, targetPosY],
                            grid);
                        emptyTileFound = true;
                        break;
                    }
                }

                if (emptyTileFound)
                {
                    break;
                }

                iMax++;
                increment *= -1;
            }

            // If the path is still null (maybe enemy is blocked off by structure), just random anyhow position to the adjacent tiles.
            if (retPath == null)
            {
                LinkedList <Node> neighbours = grid.nodes[_enemyPosX, _enemyPosY].neighbours;
                for (LinkedListNode <Node> curNode = neighbours.First; curNode != null; curNode = curNode.Next)
                {
                    if (DungeonManager.Instance.IsCellEmpty(curNode.Value.PosX, curNode.Value.PosY))
                    {
                        retPath = new LinkedList <Node>();
                        retPath.AddFirst(grid.nodes[curNode.Value.PosX, curNode.Value.PosY]);
                        retPath.AddFirst(grid.nodes[_enemyPosX, _enemyPosY]);
                        break;
                    }
                }
            }
        }

        // If STILL null (can't move all; all neighbours blocked), then no choice, return null and don't move.

        return(retPath);
    }
Beispiel #5
0
    //寻找路径
    bool FindPath(Unit _unit, NodeItem _target)
    {
        if (path != null)
        {
            ClearPath();
        }

        NodeItem unitNode = _unit.nodeItem;

        /*
         * //判断是双格单位,而且前方点更近,则使用前方点进行寻路
         * if(_unit.type.isTwoHexsUnit && (_target.pos - _unit.nodeAhead.pos).magnitude < (_target.pos - _unit.nodeItem.pos).magnitude)
         * {
         *      unitNode = _unit.nodeAhead;
         * }
         *
         * if(_unit.type.isTwoHexsUnit)
         * {
         *      //前方点不存在或被占用,则使用上个点为目的地
         *      Vector2Int pos = _target.pos;
         *      pos.x += _unit.sideFacing;
         *      if(!BattleManager.instance.map.isNodeAvailable(pos) || !BattleManager.instance.map.GetNode(pos).walkable)
         *      {
         *              pos.x -= 2 * _unit.sideFacing;
         *              _target = BattleManager.instance.map.GetNodeItem(pos);
         *      }
         * }
         */

        //根据是否是双格单位,选中寻路方法
        if (!_unit.type.isTwoHexsUnit)
        {
            path = AStarManager.FindPath(BattleManager.instance.map, unitNode, _target, !_unit.isWalker);
        }
        else
        {
            path = new List <NodeItem>();
            MapManager map = BattleManager.instance.map;

            //如果目标点的前方点不存在,或者不在可到达节点,则目标点向后移动
            Vector2Int ahead = new Vector2Int(_target.pos.x + _unit.sideFacing, _target.pos.y);
            if (!map.isNodeAvailable(ahead) || !NodeSelector.reachableNodes.Contains(map.GetNodeItem(ahead)))
            {
                _target = map.GetNodeItem(new Vector2Int(_target.pos.x - _unit.sideFacing, _target.pos.y));
            }

            foreach (var item in AStarManager.FindPath_TwoHex(map, map.GetNode(unitNode.pos), map.GetNode(_unit.nodeAhead.pos), map.GetNode(_target.pos), !_unit.isWalker))
            {
                path.Add(map.GetNodeItem(item.pos));
            }
        }

        //print(path.Count);
        if (path == null)
        {
            //print("未能找到路径");
            return(false);
        }

        path.RemoveAt(0);

        foreach (var item in path)
        {
            item.GetComponent <NodeItem_Battle>().ChangeBackgoundColor("path");
        }
        return(true);
    }
Beispiel #6
0
    //点击节点
    public override void OnNodePressed(NodeItem _node)
    {
        NodeItem_Travel   node = (NodeItem_Travel)_node;
        NodeObject_Travel obj  = (NodeObject_Travel)node.nodeObject;

        Hero hero = TravelManager.currentHero;

        if (hero == null)
        {
            Debug.LogError("当前英雄为空");
        }

        //有路径,而且点击的是终点,则开始移动。否则寻路
        if (path != null && node.pathType == TravelPathType.goal)
        {
            //是空地直接移动
            //否则移动到目标点,然后开始交互
            if (obj == null)
            {
                MoveObjectAlongPath(hero.gameObject, path);
            }
            else
            {
                targetNodeObject = obj;

                if (obj.objectType == TravelNodeType.empty)
                {
                    MoveObjectAlongPath(hero.gameObject, path);
                }
                //是英雄,或者单位,或者物品,只要移动到相邻处,就能开始交互
                else if (obj.objectType == TravelNodeType.hero ||
                         obj.objectType == TravelNodeType.unit ||
                         obj.objectType == TravelNodeType.item)
                {
                    List <NodeItem> shortPath = new List <NodeItem>(path);
                    shortPath.RemoveAt(shortPath.Count - 1);
                    MoveObjectAlongPath(hero.gameObject, shortPath);
                }
                else
                {
                    //城镇或者地点类物体,进入后交互
                    MoveObjectAlongPath(hero.gameObject, path);
                }
            }
        }
        else
        {
            //清除之前的路径显示
            ClearPath();

            path = AStarManager.FindPath(this, hero.nodeItem, _node);

            int movementRate = hero.movementRate;
            if (path != null)
            {
                NodeItem lastNode;
                for (int i = 1; i < path.Count; i++)
                {
                    lastNode = path[i - 1];

                    if (movementRate >= 0)
                    {
                        movementRate -= GetNodeDistance(lastNode, path[i]);
                    }

                    NodeItem_Travel currentNode = (NodeItem_Travel)path[i];

                    if (i == path.Count - 1)
                    {
                        //是终点
                        currentNode.UpdateStatus(TravelPathType.goal);
                    }
                    else
                    {
                        currentNode.UpdateStatus(TravelPathType.path);
                    }

                    if (movementRate >= 0)
                    {
                        currentNode.ChangeColor(color_reachable);
                    }
                    else
                    {
                        currentNode.ChangeColor(color_outOfReach);
                    }

                    lastNode.GetComponent <NodeItem_Travel>().ArrowFaceTarget(path[i].gameObject);
                }
            }
        }
    }