// (src,target]までRayCastする
        public override void RaycastCell(Vector2 src, Vector2 target, AstarCell.Type ignore, System.Func <int, int, bool> act)
        {
            if (this.UsingUnityRaycast)
            {
                var hits = Physics.SphereCastAll(new Vector3(src.x, this.TileSize * 0.6f, src.y),
                                                 this.RayCastHalfExtents, // this.TileSize * 0.5f,
                                                 new Vector3(target.x - src.x, 0.0f, target.y - src.y),
                                                 (target - src).magnitude);

                foreach (var h in hits)
                {
                    if (this.DisallowTags.Contains(h.transform.tag))
                    {
                        continue;
                    }
                    var       pos   = hits[0].transform.position;
                    int       index = this.cellIndex(new Vector2(pos.y, pos.z));
                    AstarCell cell  = null;
                    if (index >= 0 && index < this.cellMapBody.Count())
                    {
                        cell = this.cellMapBody[index];
                    }
                    ///act(cell);
                    return;
                }
                ///act(this.CellMap(target));
            }
            else
            {
                base.RaycastCell(src, target, ignore, act);
            }
        }
Esempio n. 2
0
        // 動的なセルの追加(状態変更)
        public override AstarCell AddCellImmediate(Vector2 pos, AstarCell.Type type)
        {   // グリッドタイプの場合は、既存のセルの属性を変える
            var cell = CellMap(pos);

            cell.CellType = type;
            MakeRelation(cell);
            return(cell);
        }
Esempio n. 3
0
        private void setCellType(Vector2 pos, AstarCell.Type cellType)
        {
            int ix = (int)((pos.x - this.MapRect.x) / this.TileSize + 0.5f);
            int iy = (int)((pos.y - this.MapRect.y) / this.TileSize + 0.5f);

            if (ix < 0 || ix >= this.GridWidth || iy < 0 || iy > this.GridHeight)
            {
                Debug.LogError(string.Format("invalid cell position({0},{1})", pos.x, pos.y));
            }
            else
            {
                this.cellType[ix, iy] = cellType;
            }
        }
Esempio n. 4
0
        public override AstarCell AddCellImmediate(Vector2 pos, AstarCell.Type type)
        {
            if (this.GridMode)
            {
                return(base.AddCellImmediate(pos, type));
            }
            else
            {
                AstarCell cell = null;
                if (type == AstarCell.Type.Start || type == AstarCell.Type.Goal)
                {   // スタートかゴールがブロックの場合はエラー
                    if (CellMap(pos).CellType == AstarCell.Type.Block)
                    {
                        return(null);
                    }
                }
                else
                {   // StartとGoal以外はセルを探す
                    cell = CellMap(pos);
                }

                if (cell == null)
                {
                    cell          = new AstarCell();
                    cell.CellType = type;
                    cell.Position = pos;
                    setCellType(cell);
                    MakeRelation(cell);
                    this.logic.cells.Add(cell);
                }
                else
                {
                    cell.CellType = type;
                    setCellType(cell);
                    MakeRelation(cell);
                    if (!this.logic.cells.Contains(cell))
                    {
                        this.logic.cells.Add(cell);
                    }
                }
                return(cell);
            }
        }
Esempio n. 5
0
        // 基本的なAStartでは処理が冗長のため、最適化を行う
        // 障害物の凸頂点以外のノードを削除する
        public void MapMake()
        {
            foreach (var cell in this.cellMapBody)
            {
                if (cell.CellType != AstarCell.Type.Block)
                {
                    cell.CellType = AstarCell.Type.Empty;
                }
                cell.Related.Clear();
            }

            // 8方向全部がEmptyであるセルを削除
            var octcells = this.cellMapBody.Where(c =>
            {
                if (c.CellType != AstarCell.Type.Empty)
                {
                    return(false);
                }
                for (int ix = -1; ix < 2; ++ix)
                {
                    for (int iy = -1; iy < 2; ++iy)
                    {
                        if (ix == 0 && iy == 0)
                        {
                            continue;
                        }
                        Vector2 ixy = new Vector2(ix * this.TileSize, iy * this.TileSize);
                        if (this.CellType(c.Position + ixy) != AstarCell.Type.Empty)
                        {
                            return(false);
                        }
                    }
                }
                return(true);
            }
                                                  ).ToList();

            foreach (var cell in octcells)
            {
                cell.CellType = AstarCell.Type.Removed;
            }
            var emptyCells = this.cellMapBody.Where(c => c.CellType == AstarCell.Type.Empty);

            // 3x3周囲のセル情報をセットする
            System.Action <Vector2, AstarCell.Type[, ]> set3x3 = (pos, ar) =>
            {
                for (int ix = -1; ix < 2; ++ix)
                {
                    for (int iy = -1; iy < 2; ++iy)
                    {
                        if (ix == 0 && iy == 0)
                        {
                            continue;
                        }
                        float x = pos.x + (ix * this.TileSize);
                        float y = pos.y + (iy * this.TileSize);
                        ar[ix + 1, iy + 1] = this.CellType(new Vector2(x, y));
                    }
                }
            };
            // 角以外のセルを削除
            List <AstarCell> removeList = new List <AstarCell>();

            foreach (var cell in emptyCells)
            {
                var pos = cell.Position;
                AstarCell.Type[,] ar = new AstarCell.Type[3, 3]; // check around
                set3x3(pos, ar);
                // 縦横3連ブロックチェック
                for (int inv = 0; inv < 2; ++inv)
                {
                    // x,yを反転させる
                    System.Func <int, int, AstarCell.Type> m = (x, y) => { return(inv == 0 ? ar[x, y] : ar[y, x]); };

                    // 両サイド
                    for (int s = 0; s <= 2; s += 2)
                    {
                        int u = 2 - s; // 逆サイド
                        if (m(s, 0) == m(s, 1) && m(s, 1) == m(s, 2) && m(s, 0) == AstarCell.Type.Block)
                        {              // サイドがすべてブロック
                            if (m(1, 0) == AstarCell.Type.Empty && m(1, 2) == AstarCell.Type.Empty)
                            {          // 上下3連でEmpty
                                if (m(u, 0) != AstarCell.Type.Block &&
                                    m(u, 1) != AstarCell.Type.Block &&
                                    m(u, 2) != AstarCell.Type.Block)
                                {
                                    removeList.Add(cell);
                                }
                            }
                            if (m(1, 0) == AstarCell.Type.Empty || m(1, 2) == AstarCell.Type.Empty)
                            {   // 凹角の判断
                                if ((m(1, 2) == AstarCell.Type.Block && m(u, 2) == AstarCell.Type.Block && m(u, 0) != AstarCell.Type.Block) ||
                                    (m(1, 0) == AstarCell.Type.Block && m(u, 0) == AstarCell.Type.Block && m(u, 2) != AstarCell.Type.Block))
                                {
                                    removeList.Add(cell);
                                }
                            }
                        }
                    }
                }
            }
            foreach (var cell in removeList)
            {
                cell.CellType = AstarCell.Type.Removed;
            }
            removeList.Clear();

            if (!this.GridMode)
            {   // グリッドモードでない場合は、さらに最適化を進める
                foreach (var cell in emptyCells.Where(c => c.CellType == AstarCell.Type.Empty))
                {
                    var pos = cell.Position;
                    AstarCell.Type[,] ar = new AstarCell.Type[3, 3]; // check around
                    set3x3(pos, ar);
                    // 90度つず回転する[x,y][y,x][-x,y][x,-y]
                    for (int angle = 0; angle < 8; ++angle)
                    {
                        System.Func <int, int, AstarCell.Type> m = (x, y) =>
                        {
                            switch (angle)
                            {
                            default:
                            case 0: return(ar[x, y]);

                            case 1: return(ar[y, 2 - x]);

                            case 2: return(ar[2 - x, 2 - y]);

                            case 3: return(ar[2 - y, x]);

                            case 4: return(ar[y, x]);

                            case 5: return(ar[x, 2 - y]);

                            case 6: return(ar[2 - y, 2 - x]);

                            case 7: return(ar[2 - x, y]);
                            }
                        };
                        // 角にある3点を1点にする
                        // □ □ □      □ □ □
                        // □ * *   => □ □ *
                        // ? ■ ?      ? ■ *
                        if (m(0, 0) == AstarCell.Type.Removed && m(1, 0) == AstarCell.Type.Removed && m(2, 0) == AstarCell.Type.Removed &&
                            m(0, 1) == AstarCell.Type.Removed && m(1, 1) == AstarCell.Type.Empty && m(2, 1) == AstarCell.Type.Empty &&
                            /*&& m(0,2) == AstarCell.Type.Block*/ m(1, 2) == AstarCell.Type.Block /*&& m(2, 2) == AstarCell.Type.Empty*/)
                        {
                            removeList.Add(cell);
                        }
                        // 冗長な斜めの線を細くする
                        //  □  * !□      □ * *
                        //  *  *  ■   => * □ ■
                        // !□  ■  ■      * ■ ■
                        if (angle < 4 &&
                            m(0, 0) == AstarCell.Type.Removed && m(1, 0) == AstarCell.Type.Empty && m(2, 0) != AstarCell.Type.Removed &&
                            m(0, 1) == AstarCell.Type.Empty && m(1, 1) == AstarCell.Type.Empty && m(2, 1) == AstarCell.Type.Block &&
                            m(0, 2) != AstarCell.Type.Removed && m(1, 2) == AstarCell.Type.Block && m(2, 2) == AstarCell.Type.Block)
                        {
                            removeList.Add(cell);
                        }
                        // 3連続の中を抜く
                        //  ?  *  ?      ?  *  ?
                        // !*  *  !*  => ?  □  ?
                        //  ?  *  ?      ?  *  ?
                        if ((angle == 0 || angle == 4) &&
                            m(1, 0) == AstarCell.Type.Empty && m(1, 1) == AstarCell.Type.Empty && m(1, 2) == AstarCell.Type.Empty &&
                            (m(0, 1) != AstarCell.Type.Empty && m(2, 1) != AstarCell.Type.Empty)
                            )
                        {
                            removeList.Add(cell);
                        }
                        // 斜め3連続の中を抜く
                        // !□  ?  *     □  □  *
                        //  □  *  □  => □  □  □
                        //  *  ? !□     *  □  □
                        if ((angle == 0 || angle == 7) &&
                            m(0, 0) != AstarCell.Type.Empty /*&& m(1,0) == AstarCell.Type.Removed */ && m(2, 0) == AstarCell.Type.Empty &&
                            /*&& m(0,1) == AstarCell.Type.Removed*/ m(1, 1) == AstarCell.Type.Empty && /*&& m(2,1) == AstarCell.Type.Removed*/
                            m(0, 2) == AstarCell.Type.Empty /*&& m(1,2) == AstarCell.Type.Removed */ && m(2, 2) != AstarCell.Type.Empty)
                        {
                            removeList.Add(cell);
                        }
                    }
                }

                foreach (var cell in removeList)
                {
                    cell.CellType = AstarCell.Type.Removed;
                }
            }

            // キャッシュ用セルを作成
            this.cellType = new AstarCell.Type[this.GridWidth, this.GridHeight];
            foreach (var cell in this.cellMapBody)
            {
                setCellType(cell);
            }

            // 有効なセルの登録
            this.logic.cells = this.cellMapBody.Where(c => c.CellType == AstarCell.Type.Empty).Select(c => c as AstarCell).ToList();

            // 残ったセルに対して、接続情報をセットする
            if (this.PreCalculateRelation)
            {
                foreach (var cell in this.logic.cells)
                {
                    setGridRelatedSearchRaycast(cell, true);
                    cell.RelationBuilt = true;
                }
            }

            this.MapReady = true;
        }
Esempio n. 6
0
        // (src,target] までDDAでトレースする
        // DDAでレイキャスト
        // (src,target] までDDAでトレースする
        public virtual void RaycastCell(Vector2 src, Vector2 target, AstarCell.Type ignore, System.Func <int, int, bool> act)
        {
            int ix = (int)((src.x - this.MapRect.x) / this.TileSize + 0.5f);
            int iy = (int)((src.y - this.MapRect.y) / this.TileSize + 0.5f);
            int tx = (int)((target.x - this.MapRect.x) / this.TileSize + 0.5f);
            int ty = (int)((target.y - this.MapRect.y) / this.TileSize + 0.5f);


            int sx = ix > tx ? -1 : 1;
            int sy = iy > ty ? -1 : 1;
            int dx = Mathf.Abs(tx - ix);
            int dy = Mathf.Abs(ty - iy);

            if (dx == dy)
            {   //ななめ45度
                while (true)
                {
                    ix += sx;
                    iy += sy;
                    if (--dx < 0)
                    {
                        break;
                    }
                    if (this.cellType[ix, iy] != ignore)
                    {
                        if (act(ix, iy))
                        {
                            return;
                        }
                    }
                }
            }
            else if (dx > dy)
            {   // 横に長い
                int r = dx / 2;
                while (sx > 0 ? ix <tx : ix> tx)
                {
                    ix += sx;
                    r  -= dy;
                    if (r < 0)
                    {
                        r  += dx;
                        iy += sy;
                    }
                    if (this.cellType[ix, iy] != ignore)
                    {
                        if (act(ix, iy))
                        {
                            return;
                        }
                    }
                }
            }
            else
            {   // 縦に長い
                int r = dy / 2;
                while (sy > 0 ? iy <ty : iy> ty)
                {
                    iy += sy;
                    r  -= dx;
                    if (r < 0)
                    {
                        r  += dy;
                        ix += sx;
                    }
                    if (this.cellType[ix, iy] != ignore)
                    {
                        if (act(ix, iy))
                        {
                            return;
                        }
                    }
                }
            }
        }
Esempio n. 7
0
 // 動的なセルの追加(状態変更)
 public abstract AstarCell AddCellImmediate(Vector2 pos, AstarCell.Type type);