Esempio n. 1
0
    /// <summary>
    /// 从目标列表里根据距离时间等权重筛选最有目标
    /// </summary>
    /// <param name="targeters"></param>
    /// <param name="_targetPos"></param>
    /// <param name="_targetRoute"></param>
    /// <returns></returns>
    private List <TileEntity> SelectTargeters(List <TileEntity> targeters, out TilePoint?_targetPos, out LinkedList <IMoveGrid> _targetRoute)
    {
        _targetPos   = null;
        _targetRoute = null;

        //  先在监视范围内寻找时间消耗最低的目标
        IsoGridTarget targetInfos = FindTargetsNearestTimeCost(Attacker, targeters);

        if (targetInfos != null)
        {
            Assert.Should(targetInfos.MoveRoute != null);
            if (targetInfos.MoveRoute.Count > 1)
            {
                _targetRoute = targetInfos.MoveRoute;
            }
            return(AuxConvertToList(targetInfos.Targeter));
        }

        //  未找到则直接寻找直线最近的目标
        var     nearest_targets = FindTargetsNearestLinear(Attacker.GetCurrentPositionCenter(), targeters, 1);
        var     targeter        = nearest_targets[0];
        Vector2 p = targeter.GetCurrentPositionCenter();
        //int randomOffset = Mathf.Min((int)(targeter.blockingRange / 2.0f + Attacker.model.range), targeter.width / 2);  //  TODO:如果该值过大导致移动结束后目标不在攻击范围内(则会导致重新锁定目标) 则需要酌情调整该值算法
        int randomOffset = Mathf.Min((int)Attacker.model.range, targeter.width / 2);
        int x            = (int)p.x;
        int y            = (int)p.y;

        if (randomOffset > 0)
        {
            x = BattleRandom.Range(x - randomOffset, x + randomOffset);
            y = BattleRandom.Range(y - randomOffset, y + randomOffset);
        }
        _targetPos = new TilePoint(x, y);
        return(nearest_targets);
    }
Esempio n. 2
0
    public RetvGridTargetInfo Search(int startX, int startY, Dictionary <TilePoint, IsoGridTarget> gridTargets, AStarUserContext inContext)
    {
        //  执行搜索
#if REALTIME_AI
        SearchCore(startX, startY, inContext);
#else
        foreach (var _break in SearchCore(startX, startY, inContext))
        {
            if (_break)
            {
                break;
            }
            yield return(null);
        }
#endif

        //  筛选所有权重最低的格子
        float          miniWeight    = float.MaxValue;
        IsoGridTarget  targeterInfos = null;
        DijkstraVertex vertex        = null;
        foreach (var item in gridTargets)
        {
            DijkstraVertex v = m_SearchSpace[item.Key.x, item.Key.y];
            if (v.Visited && v.Weight < miniWeight)
            {
                miniWeight    = v.Weight;
                targeterInfos = item.Value;
                vertex        = v;
            }
        }

        //  未找到直接范围
        if (targeterInfos == null)
        {
            return(null);
        }

        //  生成移动路线(从起点到目标点)
        LinkedList <IMoveGrid> route = new LinkedList <IMoveGrid>();
        for (var v = vertex; v != null; v = v.Parent)
        {
            route.AddFirst(v);
        }
        targeterInfos.MoveRoute = route;

#if REALTIME_AI
        return(targeterInfos);
#else
        yield return(targeterInfos);
#endif
    }
Esempio n. 3
0
    /// <summary>
    /// 延迟计算回调函数
    /// </summary>
    /// <param name="delayAI"></param>
    private void OnDelayLockTargetersCompleted(DelayAiObject <IsoGridTarget> delayAI)
    {
        m_tempTargetPos = null;
        m_tempMoveRoute = null;
        //Entity.State = EntityStateType.Thinking;
        IsoGridTarget targetInfos = delayAI.result;

        Assert.Should(targetInfos != null && targetInfos.MoveRoute != null);
        if (targetInfos.MoveRoute.Count > 1)
        {
            m_tempMoveRoute = targetInfos.MoveRoute;
        }
        m_tempTargeters = AuxConvertToList(targetInfos.Targeter);

        //  执行行动
        DoAction();
    }
Esempio n. 4
0
    /// <summary>
    /// 从备选目标对象列表筛选最近的目标(时间消耗最低)
    /// </summary>
    /// <param name="attacker"></param>
    /// <param name="targets"></param>
    /// <returns></returns>
    protected RetvGridTargetInfo FindTargetsNearestTimeCost(TileEntity attacker, List <TileEntity> targets)
    {
        //  备选列表 低于 需求量则不用排序直接全部返回
        if (targets.Count == 0)
        {
            return(null);
        }

        ///<    计算最近目标
        Dictionary <TilePoint, IsoGridTarget> gridTargets = new Dictionary <TilePoint, IsoGridTarget>();

        if (attacker.model.range < 3.0f)    //  REMARK:3.0f是建筑和士兵之间跨越墙的最短距离(低于3则直接根据目标点中心求最近即可、否则需要根据建筑周边被攻击范围覆盖的所有区域求最近。)
        {
            foreach (var tar in targets)
            {
                Vector2       p        = tar.GetCurrentPositionCenter();
                TilePoint     grid     = new TilePoint((int)p.x, (int)p.y);
                IsoGridTarget tarInfos = new IsoGridTarget()
                {
                    Targeter = tar, Distance = 0, X = grid.x, Y = grid.y
                };
                gridTargets.Add(grid, tarInfos);
            }
        }
        else
        {
            foreach (var tar in targets)
            {
                Vector2 p      = tar.GetCurrentPositionCenter();
                int     cx     = (int)p.x;
                int     cy     = (int)p.y;
                int     range  = (int)(attacker.model.range + Mathf.Max(0.5f, tar.blockingRange / 2.0f));
                int     bgnX   = Math.Max(cx - range, 0);
                int     endX   = Math.Min(cx + range, Constants.EDGE_WIDTH - 1);
                int     bgnY   = Math.Max(cy - range, 0);
                int     endY   = Math.Min(cy + range, Constants.EDGE_HEIGHT - 1);
                int     range2 = range * range;
                for (int x = bgnX; x <= endX; x++)
                {
                    for (int y = bgnY; y <= endY; y++)
                    {
                        int dx   = cx - x;
                        int dy   = cy - y;
                        int diff = dx * dx + dy * dy;
                        if (diff <= range2 && IsoMap.Instance.IsPassable(x, y))
                        {
                            TilePoint grid = new TilePoint(x, y);
                            if (gridTargets.ContainsKey(grid))
                            {
                                IsoGridTarget tarInfos = gridTargets[grid];
                                if (diff < tarInfos.Distance)
                                {
                                    tarInfos.Distance = diff;
                                    tarInfos.Targeter = tar;
                                }
                            }
                            else
                            {
                                IsoGridTarget tarInfos = new IsoGridTarget()
                                {
                                    Targeter = tar, Distance = diff, X = grid.x, Y = grid.y
                                };
                                gridTargets.Add(grid, tarInfos);
                            }
                        }
                    }
                }
            }
        }
        if (gridTargets.Count == 0)
        {
            return(null);
        }
#if REALTIME_AI
        return(IsoMap.Instance.SearchDijkstra(attacker, gridTargets));
#else
        return(IsoMap.Instance.SearchDijkstra(attacker, gridTargets));
#endif
    }
Esempio n. 5
0
    protected override List <TileEntity> TryLockTargeters(out TilePoint?_targetPos, out LinkedList <IMoveGrid> _targetRoute)
    {
        _targetPos   = null;
        _targetRoute = null;

        ///<    有目标了直接返回
        if (m_tempTargeters != null)
        {
            return(m_tempTargeters);
        }

        ///<    方案1:计算全地图目标时间最近(并且有墙的路线)REMARK:有墙基本就可以理解为封闭区域
        Dictionary <TilePoint, IsoGridTarget> gridTargets = new Dictionary <TilePoint, IsoGridTarget>();
        var targets = IsoMap.Instance.GetEntitiesByTT(Attacker.GetTargetOwner(), EntityAiType.Other, Attacker);

        foreach (var tar in targets)
        {
            Vector2       p        = tar.GetCurrentPositionCenter();
            TilePoint     grid     = new TilePoint((int)p.x, (int)p.y);
            IsoGridTarget tarInfos = new IsoGridTarget()
            {
                Targeter = tar, Distance = 0, X = grid.x, Y = grid.y
            };
            gridTargets.Add(grid, tarInfos);
        }
        LinkedList <IMoveGrid> route = IsoMap.Instance.SearchDijkstraNearestWall(Attacker, gridTargets);

        if (route != null)
        {
            Assert.Should(route.Count >= 2);
            //  墙的位置
            IMoveGrid wallGrid = route.Last.Value;
            route.RemoveLast();
            //  墙的前一格
            IMoveGrid lastGrid = route.Last.Value;
            //  获取墙
            TileEntity wallTargeter = IsoMap.Instance.GetWallTargeter(lastGrid.X, lastGrid.Y, wallGrid.X, wallGrid.Y);
            Assert.Should(wallTargeter != null);
            //  返回
            _targetRoute = route;
            return(AuxConvertToList(wallTargeter));
        }

        ///<    方案2:求最近的墙o.o
        TileEntity targeter = GetWallEntityNearest(Attacker);

        if (targeter == null)
        {
            return(null);
        }

        //  查找移动目标点(墙四周离自身最近的点)
        int self_x = Entity.GetTilePos().x;
        int self_y = Entity.GetTilePos().y;

        Vector2 c      = targeter.GetCurrentPositionCenter();
        int     wall_x = (int)c.x;
        int     wall_y = (int)c.y;
        int     wall_w = 1; //   REMARK:连接器到墙中心的距离

        int mindiff = 999999;
        int goal_x  = -1;
        int goal_y  = -1;

        //  依次为 左上、右上、左下、右下
        DetectNearestGrid(ref mindiff, ref goal_x, ref goal_y, self_x, self_y, wall_x, wall_y + wall_w);
        DetectNearestGrid(ref mindiff, ref goal_x, ref goal_y, self_x, self_y, wall_x + wall_w, wall_y);
        DetectNearestGrid(ref mindiff, ref goal_x, ref goal_y, self_x, self_y, wall_x - wall_w, wall_y);
        DetectNearestGrid(ref mindiff, ref goal_x, ref goal_y, self_x, self_y, wall_x, wall_y - wall_w);

        //  找到目标点 并且 目标点位置不是自身位置
        if (goal_x >= 0 && goal_y >= 0 && ((goal_x != self_x || goal_y != self_y)))
        {
            _targetPos = new TilePoint(goal_x, goal_y);
        }

        return(AuxConvertToList(targeter));
    }