// (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);
            }
        }
        public void PathFind(AstarCell startCell,
                             AstarCell goalCell,
                             System.Action <AstarCell> makeRelation,
                             System.Action <List <Vector2> > onGoal,
                             bool initOnly = false)
        {
            if (this.Busy)
            {
                throw new System.InvalidOperationException();
            }
            this.Busy         = true;
            this.startCell    = startCell;
            this.goalCell     = goalCell;
            this.MakeRelation = makeRelation;
            this.onGoal       = onGoal;
            this.pathCount    = 0;
            this.finished     = false;
            this.goalCandidate.Clear();

            ScanAround(this.startCell);

            if (!initOnly)
            {
                while (!this.finished)
                {
                    pathFindProcess();
                }
            }
        }
        private void drawCell(AstarCell cell)
        {
            float x = cell.Position.x;
            float y = cell.Position.y;
            float t = this.TileSize * 0.4f;

            Color[] coltbl = { Color.green,// empty
                               Color.blue, Color.yellow, Color.white, Color.gray, Color.black, Color.red, new Color(0.1f, 0.1f, 0.1f, 0.1f),
                               Color.red };
            var     color = coltbl[(int)cell.CellType];

            if (cell.CellType != Tsl.Math.Pathfinder.AstarCell.Type.Removed)
            {
                Debug.DrawLine(new Vector3(x - t, 0.1f, y - t), new Vector3(x + t, 0.1f, y - t), color, 1.0f, false);
                Debug.DrawLine(new Vector3(x + t, 0.1f, y - t), new Vector3(x + t, 0.1f, y + t), color, 1.0f, false);
                Debug.DrawLine(new Vector3(x + t, 0.1f, y + t), new Vector3(x - t, 0.1f, y + t), color, 1.0f, false);
                Debug.DrawLine(new Vector3(x - t, 0.1f, y + t), new Vector3(x - t, 0.1f, y - t), color, 1.0f, false);

                foreach (var r in cell.Related)
                {
                    var p = r.cell.Position;
                    Debug.DrawLine(new Vector3(x, 0.1f, y), new Vector3(p.x, 0.1f, p.y), new Color(0.0f, 1.0f, 1.0f, 0.2f));
                }
            }
        }
Пример #4
0
        // 上下左右斜めのグリッドに対してリンクを作成する
        public override void MakeRelation(AstarCell parent)
        {
            parent.Related.Clear();
            if (parent.CellType == AstarCell.Type.Block)
            {
                return;
            }
            int x = (int)parent.Position.x;
            int y = (int)parent.Position.y;

            for (int dx = -1; dx < 2; ++dx)
            {
                for (int dy = -1; dy < 2; ++dy)
                {
                    if (dx == 0 && dy == 0)
                    {
                        continue;
                    }
                    float   nx = x + dx * this.TileSize;
                    float   ny = y + dy * this.TileSize;
                    Vector2 n  = new Vector2(nx, ny);
                    if (!this.MapRect.Contains(n))
                    {
                        continue;
                    }
                    var cell = this.CellMap(n);
                    if (cell != null && cell.CellType != AstarCell.Type.Block)
                    {
                        parent.AddRelated(this.CellMap(n), parent.Heuristic(cell));
                    }
                }
            }
            parent.RelationBuilt = true;
        }
Пример #5
0
        // intで評価されるmapRectのグリッドセルで初期化
        public void MapInit(Rect mapRect, float tilesize = 0.0f)
        {
            if (tilesize != 0.0f)
            {
                this.TileSize = tilesize;
            }
            this.MapRect = mapRect;

            // グリッドのサイズを計算しておく
            this.GridWidth  = (int)(this.MapRect.width / this.TileSize + 0.5f);
            this.GridHeight = (int)(this.MapRect.height / this.TileSize + 0.5f);

            // グリッドを埋め尽くすセルの配列
            this.cellMapBody = new AstarCell[this.GridHeight * this.GridWidth];

            // グリッドをセルの実体で埋め尽くす
            for (int iy = 0; iy < this.GridHeight; ++iy)
            {
                float y = mapRect.y + iy * this.TileSize;
                for (int ix = 0; ix < this.GridWidth; ++ix)
                {
                    float x    = mapRect.x + ix * this.TileSize;
                    var   cell = new AstarCell();
                    cell.Position = new Vector2(x, y);
                    cellMapBody[cellIndex(cell.Position)] = cell;
                }
            }
        }
Пример #6
0
 // 動的なセルの削除
 public override void RemoveCell(AstarCell cell)
 {
     if (cell != null)
     {
         setCellType(cell.Position, AstarCell.Type.Removed);
         base.RemoveCell(cell);
     }
 }
Пример #7
0
 // 接続情報を生成する
 public override void MakeRelation(AstarCell cell)
 {
     if (this.logic.cells == null)
     {
         Debug.LogError("this.logic.cells is null");
         throw new System.InvalidOperationException();
     }
     // if (!this.logic.cells.Contains(cell)) this.logic.cells.Add(cell);
     setGridRelatedSearchRaycast(cell, true);
     cell.RelationBuilt = true;
 }
Пример #8
0
        public void PathFind(Vector2 start,
                             Vector2 goal,
                             System.Action <List <Vector2> > onEnd = null,
                             ExecuteMode mode = ExecuteMode.ASync)
        {
            this.executeMode = mode;
            System.Action <List <Vector2> > onFinish = r =>
            {
                RemoveCell(this.startCell);
                RemoveCell(this.goalCell);
                if (this.DebugHaltMode && r == null)
                {
                    this.DebugHalt = true;
                }
                else
                {
                    onEnd(r);
                }
            };

            if (mode != ExecuteMode.StepNext)
            {   // 初回のPathFind
                this.goalCell  = AddCellImmediate(goal, AstarCell.Type.Goal);
                this.startCell = AddCellImmediate(start, AstarCell.Type.Start);
                if (this.startCell == null || this.goalCell == null)
                {
                    Debug.LogWarning("start or gold is in block");
                    RemoveCell(this.startCell);
                    RemoveCell(this.goalCell);
                    Reset(false);
                    onEnd(null);
                    return;
                }
                this.logic.PathFind(startCell, goalCell, this.MakeRelation, onFinish, mode != ExecuteMode.Sync);
                return;
            }
            switch (mode)
            {
            case ExecuteMode.Sync:
                break;

            case ExecuteMode.ASync:
                pathFindProcessCoroutine();
                break;

            case ExecuteMode.StepFirst:
            case ExecuteMode.StepNext:
                this.logic.pathFindProcess();
                break;

            default:
                throw new System.InvalidOperationException();
            }
        }
Пример #9
0
 // 動的なセルの削除
 public override void RemoveCell(AstarCell cell)
 {
     foreach (var target in cell.Related)
     {   // taget はcellからの接続先
         var found = target.cell.Related.Find(c => c.cell == cell);
         if (found.cell == cell)
         {
             target.cell.Related.Remove(found);
         }
     }
     this.logic.cells.Remove(cell);
 }
 private void drawCellCorrect(AstarCell cell)
 {
     if (cell.CellType == AstarCell.Type.Correct || cell.CellType == AstarCell.Type.Start || cell.CellType == AstarCell.Type.Goal)
     {
         foreach (var r in cell.Related)
         {
             if (r.cell.CellType == Tsl.Math.Pathfinder.AstarCell.Type.Correct)
             {
                 var p = r.cell.Position;
                 Debug.DrawLine(new Vector3(cell.Position.x, 0.1f, cell.Position.y), new Vector3(p.x, 0.1f, p.y), Color.red, 1.0f, false);
             }
         }
     }
 }
Пример #11
0
 public void Reset(bool allReset)
 {
     if (allReset)
     {
         this.CellType = Type.Removed;
     }
     else
     {
         if (this.CellType != Type.Removed && this.CellType != Type.Block)
         {
             this.CellType = Type.Empty;
         }
     }
     this.Score  = 0.0f;
     this.Cost   = 0.0f;
     this.Hint   = 0.0f;
     this.Parent = null;
 }
Пример #12
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);
            }
        }
        private void pathfindFinished(AstarCell cell)
        {
            var pathList = new List <Vector2>();

            pathList.Add(this.goalCell.Position);
            var parent = cell;

            while (parent.Parent != null)
            {
                pathList.Add(parent.Position);
                parent.CellType = AstarCell.Type.Correct;
                parent          = parent.Parent;
            }
            pathList.Add(this.startCell.Position);
            pathList.Reverse();
            this.finished = true;
            this.onGoal(pathList);
            //var links = this.cells.Sum(c => c.Related.Count);
            //Debug.Log(string.Format("{0} cells {1} links", this.cells.Count, links));
            this.Busy = false;
        }
Пример #14
0
        // intで評価されるmapRectのグリッドセルで初期化
        public void MapInit(int columns, int rows)
        {
            // グリッドのサイズを計算しておく
            this.GridColumns = columns;
            this.GridRows    = rows;

            // グリッドを埋め尽くすセルの配列
            this.cellMapBody = new AstarCell[(this.GridColumns + 1) / 2, this.GridRows];

            // グリッドをセルの実体で埋め尽くす
            for (int iy = 0; iy < this.GridRows; ++iy)
            {
                for (int ix = 0; ix < (this.GridColumns + 1) / 2; ++ix)
                {
                    var   cell = new AstarCell();
                    float x    = ix + ((iy & 1) == 0 ? 0.0f : cos60);
                    float y    = iy * sin60;
                    cell.Position       = new Vector2(x, y);
                    cellMapBody[ix, iy] = cell;
                }
            }
        }
Пример #15
0
 public override void MakeRelation(AstarCell cell)
 {
     if (this.logic.cells == null)
     {
         Debug.LogError("this.logic.cells is null");
         throw new System.InvalidOperationException();
     }
     cell.Related.Clear();
     for (int iy = -1; iy <= 1; ++iy)
     {
         float y = cell.Position.y + iy * sin60;
         for (int ix = -1; ix <= 1; ix += 2)
         {
             float x;
             if (iy == 0)
             {
                 x = cell.Position.x + ix;
             }
             else
             {
                 x = cell.Position.x + ix * cos60;
             }
             var c = FindCell(new Vector2(x, y));
             if (c != cell && c != null)
             {
                 if (!cell.Contains(c))
                 {
                     cell.AddRelated(c, c.MoveCost);
                 }
                 if (!c.Contains(cell))
                 {
                     c.AddRelated(cell, cell.MoveCost);
                 }
             }
         }
     }
     cell.RelationBuilt = true;
 }
        private void ScanAround(AstarCell parent)
        {
            // 接続情報を作成する
            if (!parent.RelationBuilt)
            {
                MakeRelation(parent);
            }

            foreach (var related in parent.Related)
            {
                if (related.cell.CellType == AstarCell.Type.Goal)
                {   // !! GOAL!
                    var goalcost = parent.Cost + related.cost;
                    related.cell.Cost  = goalcost;
                    related.cell.Score = goalcost;
                    if (this.goalCandidate.ContainsKey(goalcost))
                    {
                        this.goalCandidate[goalcost] = parent;
                    }
                    else
                    {
                        this.goalCandidate.Add(goalcost, parent);
                    }
                }
                float cost  = parent.Cost + related.cost;
                float hint  = this.goalCell.Heuristic(related.cell);
                float score = cost + hint;
                if (related.cell.CellType == AstarCell.Type.Empty || related.cell.Score > score)
                {
                    related.cell.Cost     = cost;
                    related.cell.Hint     = hint;
                    related.cell.Score    = score;
                    related.cell.Parent   = parent;
                    related.cell.CellType = AstarCell.Type.Open;
                }
            }
        }
Пример #17
0
 public bool Contains(AstarCell cell)
 {
     return(this.Related.Any(r => r.cell == cell));
 }
Пример #18
0
 public void AddRelated(AstarCell cell, float cost)
 {
     this.Related.Add(new RelatedData {
         cell = cell, cost = cost
     });
 }
Пример #19
0
 public float Heuristic3D(AstarCell cell)
 {
     return(((cell as AstarCell3D).Position3D - this.Position3D).magnitude);
 }
Пример #20
0
 private void setCellType(AstarCell cell)
 {
     setCellType(cell.Position, cell.CellType);
 }
Пример #21
0
 // 到達可能なノードを全ノードからレイキャストして調べる
 public void setGridRelatedSearchRaycast(AstarCell parent, bool newCell = false)
 {
     foreach (var cell in this.logic.cells.Where(c => c.IsValidCell()))
     {
         if (cell == parent)
         {
             continue;
         }
         var fromCell = cell.Find(parent);
         if (fromCell.cell != null)
         {   // 相手から自分が見えている場合
             if (!parent.Contains(cell))
             {
                 parent.AddRelated(cell, fromCell.cost);
             }
             continue;
         }
         // raycast
         float cost    = 0;
         var   prevPos = parent.Position;
         if (!this.GridMode)
         {   // 中間グリッドを飛ばして最短距離で結ぶ場合
             RaycastCell(parent.Position, cell.Position, AstarCell.Type.Removed,
                         (ix, iy) =>
             {
                 var cellType = this.cellType[ix, iy];
                 if (cellType != AstarCell.Type.Removed)
                 {           // 何かあった
                     if (cellType != AstarCell.Type.Block)
                     {       // ブロックもしくは圏外ではない場合
                         var rcell = this.Cell(ix, iy);
                         if ((rcell.Position - cell.Position).sqrMagnitude < 0.1f)
                         {           // 見つかった!
                             if (!parent.Contains(cell))
                             {
                                 cost = (cell.Position - parent.Position).magnitude;
                                 parent.AddRelated(cell, cost);
                                 if (newCell && !cell.Contains(parent))
                                 {
                                     cell.AddRelated(parent, cost);
                                 }
                             }
                         }
                     }
                     return(true);
                 }
                 else
                 {
                     return(false);
                 }
             });
         }
         else
         {   // グリッドモード
             RaycastCell(parent.Position, cell.Position, AstarCell.Type.NoIgnore,
                         (ix, iy) =>
             {
                 var rcell = this.Cell(ix, iy);
                 // グリッドモードではコストを計算する
                 var nowpos = rcell.Position;
                 cost      += (nowpos - prevPos).magnitude;
                 prevPos    = nowpos;
                 if (rcell.CellType != AstarCell.Type.Removed)
                 {         // 何かあった
                     if (rcell.CellType != AstarCell.Type.Block)
                     {     // ブロックもしくは圏外ではない場合
                         if (rcell == cell)
                         { // 見つかった!
                             if (!parent.Contains(cell))
                             {
                                 if (!this.GridMode)
                                 {
                                     cost = (cell.Position - parent.Position).magnitude;
                                 }
                                 parent.AddRelated(cell, cost);
                                 if (newCell && !cell.Contains(parent))
                                 {
                                     cell.AddRelated(parent, cost);
                                 }
                             }
                         }
                     }
                     return(true);
                 }
                 else
                 {
                     return(false);
                 }
             });
         }
     }
 }
Пример #22
0
 public RelatedData Find(AstarCell cell)
 {
     return(this.Related.Find(r => r.cell == cell));
 }
Пример #23
0
 // 動的なセルの削除
 public abstract void RemoveCell(AstarCell cell);
Пример #24
0
 // セル間の接続情報の生成
 public abstract void MakeRelation(AstarCell cell);
Пример #25
0
 public float Heuristic(AstarCell cell)
 {
     return((cell.Position - this.Position).magnitude);
 }
Пример #26
0
 // 動的なセルの削除
 public override void RemoveCell(AstarCell cell)
 {
     cell.CellType = AstarCell.Type.Empty;
 }