コード例 #1
0
        private NavigationData GetEmptyNavigationData(GridUnitData _thisGrid, NavigationData _preGrid, int _G, int _H)
        {
            //优先从池子里取出
            NavigationData nd = null;

            if (curUsedIdx < navigationDataPool.Count)
            {
                nd = navigationDataPool[curUsedIdx];
            }
            else
            {
                nd = new NavigationData();
                navigationDataPool.Add(nd);
            }

            ++curUsedIdx;

            nd.thisGrid         = _thisGrid;
            nd.preGrid          = _preGrid;
            nd.G                = _G;
            nd.H                = _H;
            nd.F                = _G + _H;
            nd.open             = true;
            nd.thisGrid.tempRef = nd;

            return(nd);
        }
コード例 #2
0
        //准备加载战场
        private void PrepareBattleMap()
        {
            if (currentData == null)
            {
                EUtilityHelperL.LogError("Prepare battle map failed. No battle data.");
                return;
            }
            gridUnits = new GridUnit[currentData.mapWidth, currentData.mapHeight];

            for (int row = 0; row < currentData.mapHeight; ++row)
            {
                for (int column = 0; column < currentData.mapWidth; ++column)
                {
                    GridUnitData gud = currentData.mapGrids[column, row];
                    if (gud != null)
                    {
                        //创建一个用于显示的格子对象
                        GridUnit gu = CreateGrid();
                        if (gu != null)
                        {
                            gridUnits[column, row]     = gu;
                            gu.transform.localPosition = gud.localPosition;
                            gu.name     = string.Format("Grid_{0}_{1}", row, column);
                            gu.gridData = gud;
                            gu.Refresh();
                            gu.gameObject.SetActive(true);
                        }
                    }
                }
            }
        }
コード例 #3
0
ファイル: BattleField.cs プロジェクト: yxpandjay/HalfSLG
        //准备加载战场
        private void PrepareBattleMap()
        {
            if (currentData == null)
            {
                EUtilityHelperL.LogError("Prepare battle map failed. No battle data.");
                return;
            }
            gridUnits = new GridUnit[currentData.mapData.mapWidth, currentData.mapData.mapHeight];

            for (int r = 0; r < currentData.mapData.mapHeight; ++r)
            {
                for (int c = 0; c < currentData.mapData.mapWidth; ++c)
                {
                    GridUnitData gud = currentData.mapData.mapGrids[c, r];
                    if (gud != null)
                    {
                        //创建一个用于显示的格子对象
                        GridUnit gridUnit = CreateGrid();
                        if (gridUnit != null)
                        {
                            gridUnits[c, r] = gridUnit;
                            gridUnit.transform.localPosition = gud.localPosition;
                            gridUnit.name     = string.Format("Grid_{0}_{1}", r, c);
                            gridUnit.gridData = gud;
                            gridUnit.RefreshColor();
                            gridUnit.gameObject.SetActive(true);
                        }
                    }
                }
            }
        }
コード例 #4
0
ファイル: BattleMapData.cs プロジェクト: yxpandjay/HalfSLG
        //放置一些障碍格子
        private void GenerateObstacle(int obstacleCount, int gap)
        {
            //随机范围
            List <GridUnitData> randomRange = new List <GridUnitData>();
            //减掉不能随机的格子
            List <GridUnitData> reduction = new List <GridUnitData>();

            //将普通格子放入
            foreach (var grid in mapGrids)
            {
                if (grid.GridType == GridType.Normal)
                {
                    randomRange.Add(grid);
                }
            }

            int count = obstacleCount;

            while (count > 0 && randomRange.Count > 0)
            {
                int          randIdx    = Random.Range(0, randomRange.Count);
                GridUnitData randomGrid = randomRange[randIdx];
                randomGrid.GridType = GridType.Obstacle;
                //排除格子周围的格子
                GetRangeGrids(randomGrid.row, randomGrid.column, gap, reduction);
                if (reduction.Count > 0)
                {
                    foreach (var item in reduction)
                    {
                        randomRange.Remove(item);
                    }
                }
                --count;
            }
        }
コード例 #5
0
        //计算两格子之间的距离
        public int Distance(GridUnitData target)
        {
            //行之间的差
            int rowGap = Mathf.Abs(target.row - row);
            //移动行后所覆盖的最小、最大横坐标
            int minColumn = 0;
            int maxColumn = 0;

            //奇数行开始时
            if ((row & 1) == (EGameConstL.Map_FirstRowOffset ? 0 : 1))
            {
                minColumn = Mathf.Max(column - (rowGap / 2), 0);
                maxColumn = column + ((rowGap + 1) / 2);
            }
            //偶数行开始时
            else
            {
                minColumn = Mathf.Max(column - ((rowGap + 1) / 2), 0);
                maxColumn = column + (rowGap / 2);
            }
            //在移动范围之外,额外增加
            if (target.column < minColumn)
            {
                return(rowGap + minColumn - target.column);
            }
            else if (target.column > maxColumn)
            {
                return(rowGap + target.column - maxColumn);
            }
            //在移动范围之内,因此行移动量就是两格子的距离
            else
            {
                return(rowGap);
            }
        }
コード例 #6
0
        public override bool Equals(object obj)
        {
            if (obj is GridUnitData)
            {
                GridUnitData data = (GridUnitData)obj;
                return(data.mapID == mapID &&
                       data.row == row &&
                       data.column == column);
            }

            return(false);
        }
コード例 #7
0
            public void Reset()
            {
                open = true;

                F = 0;
                G = 0;
                H = 0;

                //清空关联
                if (thisGrid != null)
                {
                    thisGrid.tempRef = null;
                    thisGrid         = null;
                }

                preGrid = null;
            }
コード例 #8
0
        //设置格子类型
        private void SetGridType(GridUnitData gud, GridType gt)
        {
            switch (gt)
            {
            case GridType.Normal:
                normalGrids.Add(gud);
                break;

            case GridType.Obstacle:
                obstacleGrids.Add(gud);
                break;

            default:
                break;
            }
            gud.gridType = gt;
        }
コード例 #9
0
        //战场中铺设格子(信息)
        public void Generate(int width, int height, int obstacle, int gap)
        {
            if (width <= 0 || height <= 0)
            {
                return;
            }

            //地图编号自增
            mapID = mapCount++;
            //记录地图宽高
            mapWidth  = width;
            mapHeight = height;
            //生成格子数组
            mapGrids = new GridUnitData[mapWidth, mapHeight];
            //记录普通格子和障碍格子
            normalGrids   = new List <GridUnitData>();
            obstacleGrids = new List <GridUnitData>();

            //全部生成为普通格子
            for (int r = 0; r < mapHeight; ++r)
            {
                for (int c = 0; c < mapWidth; ++c)
                {
                    GridUnitData gud = new GridUnitData();
                    gud.localPosition = new Vector3(
                        c * EGameConstL.GridWidth + ((r & 1) > 0 ? (EGameConstL.GridWidth * 0.5f) : 0f),
                        -r * EGameConstL.GridOffsetY,
                        0
                        );

                    //设置格子参数
                    gud.gridPosition = new Vector2Int(r, c);     //位置
                    //初始设置为普通格子
                    SetGridType(gud, GridType.Normal);
                    //保存
                    mapGrids[c, r] = gud;
                }
            }

            //随机一些障碍格子
            DisposeGridUnits(obstacle, gap);
        }
コード例 #10
0
ファイル: BattleMapData.cs プロジェクト: yxpandjay/HalfSLG
        //战场中铺设格子
        public void Generate(int width, int height, int obstacleCount, int gap)
        {
            EUtilityHelperL.TimerStart();

            if (width <= 0 || height <= 0)
            {
                return;
            }

            //记录地图宽高
            mapWidth  = width;
            mapHeight = height;
            //生成格子数组
            mapGrids = new GridUnitData[mapWidth, mapHeight];

            //全部生成为普通格子
            for (int r = 0; r < mapHeight; ++r)
            {
                for (int c = 0; c < mapWidth; ++c)
                {
                    GridUnitData gridUnitData = new GridUnitData(mapID, r, c);
                    gridUnitData.localPosition = new Vector3(
                        c * EGameConstL.Map_GridWidth + ((r & 1) == (EGameConstL.Map_FirstRowOffset ? 0 : 1) ? (EGameConstL.Map_GridWidth * 0.5f) : 0f),
                        -r * EGameConstL.Map_GridOffsetY,
                        0
                        );

                    //初始设置为普通格子
                    gridUnitData.GridType = GridType.Normal;
                    //保存
                    mapGrids[c, r] = gridUnitData;
                }
            }
            //随机一些障碍格子
            GenerateObstacle(obstacleCount, gap);
            //整理格子列表
            TidyGridList();

            EUtilityHelperL.Log(string.Format("Generate map {0}, time cost:{1}", mapID, EUtilityHelperL.TimerEnd()));
        }
コード例 #11
0
        //计算两格子之间的距离
        public int Distance(GridUnitData target)
        {
            //计算行移动量
            int rowGap = Mathf.Abs(target.gridPosition.x - gridPosition.x);
            //列范围 - x
            int offset = (((rowGap & 1) == 0) ? 0 : 1) + rowGap / 2;

            //如果在范围内,移动量就是行移动量
            if (target.gridPosition.y >= (gridPosition.y - offset) && (target.gridPosition.y <= (gridPosition.y + offset)))
            {
                //Debug.Log(string.Format("({0},{1})->({2},{3})->{4}", target.row, target.column, row, column, rowGap));
                return(rowGap);
            }
            else if (target.gridPosition.y > (gridPosition.y + offset))
            {
                //Debug.Log(string.Format("({0},{1})->({2},{3})->{4}", target.row, target.column, row, column, rowGap + (target.column - column - offset)));
                return(rowGap + (target.gridPosition.y - gridPosition.y - offset));
            }
            else
            {
                //Debug.Log(string.Format("({0},{1})->({2},{3})->{4}", target.row, target.column, row, column, rowGap + column - offset - target.column));
                return(rowGap + gridPosition.y - offset - target.gridPosition.y);
            }
        }
コード例 #12
0
        //放置一些障碍格子
        private void DisposeGridUnits(int obstacle, int gap)
        {
            obstacle = Mathf.Min(mapWidth * mapHeight, obstacle);

            for (int i = 0; i < obstacle; ++i)
            {
                int          randomIdx = -1;
                GridUnitData target    = null;
                int          tryTimes  = 999;
                while (tryTimes > 0 && target == null)
                {
                    randomIdx = Random.Range(0, normalGrids.Count);
                    target    = normalGrids[randomIdx];
                    //判断距离
                    for (int j = 0; j < obstacleGrids.Count; ++j)
                    {
                        var distance = obstacleGrids[j].Distance(target);
                        if (obstacleGrids[j].Distance(target) < gap)
                        {
                            target = null;
                            break;
                        }
                    }
                    --tryTimes;
                }
                if (target != null)
                {
                    SetGridType(target, GridType.Obstacle);
                    normalGrids.RemoveAt(randomIdx);
                }
                else
                {
                    EUtilityHelperL.LogWarning("Dispose grid unit data warning.");
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// 导航
        /// </summary>
        /// <param name="battleMap">地图信息</param>
        /// <param name="from">从哪出发</param>
        /// <param name="to">到哪里去</param>
        /// <param name="path">路径</param>
        /// <param name="searched">探索过但没采用的</param>
        /// <returns>是否导航成功</returns>
        public bool Navigate(
            BattleMapData battleMap,
            GridUnitData from,
            GridUnitData to,
            List <GridUnitData> path,
            List <GridUnitData> searched)
        {
            //没有设置地图
            if (battleMap == null)
            {
                return(false);
            }

            if (path != null)
            {
                path.Clear();
            }
            if (searched != null)
            {
                searched.Clear();
            }

            int tryTimes = battleMap.GridCount;

            List <NavigationData> opening = new List <NavigationData>();

            opening.Add(GetEmptyNavigationData(from, null, 0, from.Distance(to)));

            int  retry   = 0;
            bool catched = false;

            //当前探索方向
            int curDir = 0;
            //上次探索方向
            int lastDir = 0;
            //每次检测方向的次数
            int checkTimes = 0;

            //判断是否需要遍历open列表
            NavigationData gift = null;

            //距离最近的格子(接下来要移动的)
            NavigationData next_0 = null;
            //距离次近的格子
            NavigationData next_1 = null;

            int minStep = EGameConstL.Infinity;

            while (retry <= tryTimes && !catched)
            {
                ++retry;
                //从open中查找最近的节点
                if (gift != null)
                {
                    next_0 = gift;
                    gift   = null;
                }
                else if (next_1 != null)
                {
                    next_0 = next_1;
                    next_1 = null;
                }
                else
                {
                    minStep = EGameConstL.Infinity;

                    for (int i = opening.Count - 1; i >= 0; --i)
                    {
                        if (!opening[i].open)
                        {
                            opening.RemoveAt(i);
                        }
                        else if (opening[i].F < minStep)
                        {
                            next_0  = opening[i];
                            minStep = next_0.F;
                        }
                        else if (next_1 == null && next_0 != null && opening[i].F == next_0.F)
                        {
                            next_1 = opening[i];
                        }
                    }
                }

                //标志为已关闭
                next_0.open = false;

                //放入已搜索中
                if (searched != null)
                {
                    searched.Add(next_0.thisGrid);
                }

                checkTimes = 6;
                curDir     = lastDir;
                //遍历最近节点的周围6个节点,依次放入close中
                int roads = next_0.thisGrid.passes;
                while (checkTimes > 0)
                {
                    //沿着当前探索方向继续探索
                    if ((roads & (1 << curDir)) != 0)
                    {
                        //获取该路通向的下一个item
                        GridUnitData sibling = battleMap.GetGridDataByDir(next_0.thisGrid.row, next_0.thisGrid.column, curDir);
                        if (sibling == null)
                        {
                            //没路
                            ++curDir;
                            curDir = (curDir > 5) ? 0 : curDir;
                            --checkTimes;
                            continue;
                        }
                        //如果这个不能移动
                        else if (sibling.GridType == GridType.Obstacle)
                        {
                            //没路
                            ++curDir;
                            curDir = (curDir > 5) ? 0 : curDir;
                            --checkTimes;
                            continue;
                        }
                        else
                        {
                            //如果这个item就是目标
                            if (sibling.Equals(to))
                            {
                                catched = true;
                                if (path != null)
                                {
                                    NavigationData current = next_0;
                                    while (current != null)
                                    {
                                        if (current.thisGrid != from)
                                        {
                                            path.Add(current.thisGrid);
                                        }
                                        current = current.preGrid;
                                    }
                                }

                                break;
                            }
                            else
                            {
                                //尝试判断这个是否为closed
                                NavigationData nd = sibling.tempRef == null ? null : (NavigationData)(sibling.tempRef);
                                if (nd == null)
                                {
                                    //这个格子没有探索过,新建并添加
                                    nd = GetEmptyNavigationData(sibling, next_0, next_0.G + 1, sibling.Distance(to));
                                    //这个格子不错哦
                                    if (nd.F <= next_0.F && gift == null)
                                    {
                                        //保存礼物
                                        gift = nd;
                                        //记录下次起始的更新方向
                                        lastDir = curDir;
                                    }
                                    //比第二目标好
                                    else if (next_1 != null && nd.F < next_1.F)
                                    {
                                        //替换第二目标
                                        next_1 = nd;
                                        opening.Add(nd);
                                    }
                                    else
                                    {
                                        //已经设置了礼物,因此只能放入opening列表中,以后再更新了呢
                                        opening.Add(nd);
                                    }
                                }
                                else
                                {
                                    //只处理没有被探索过的格子
                                    if (nd.open)
                                    {
                                        //已经在Open列表中了
                                        if ((next_0.G + 1) < nd.G)
                                        {
                                            //比原来的近,应该不可能
                                            nd.G        = next_0.G + 1;
                                            nd.H        = sibling.Distance(to);
                                            nd.F        = nd.G + nd.H;
                                            nd.preGrid  = next_0;
                                            nd.thisGrid = sibling;
                                        }
                                        //这个格子不错哦
                                        if (nd.F <= next_0.F && gift == null)
                                        {
                                            gift = nd;
                                            //保存当前探索方向
                                            lastDir = curDir;
                                        }
                                        else if (next_1 != null && nd.F < next_1.F)
                                        {
                                            //替换第二目标
                                            next_1 = nd;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    ++curDir;
                    curDir = (curDir > 5) ? 0 : curDir;
                    --checkTimes;
                }
            }

            opening.Clear();

            //重置池子
            ResetPool();

            return(catched);
        }