예제 #1
0
파일: Pathfinder.cs 프로젝트: vrobel/mooege
        public List<Vector3D> FindPath(Actor actor, Vector3D Start, Vector3D Destination)
        {
            _baseX = 0; _baseY = 0; // reset to 0

            // Should only be null first time a path is requested.
            if (_curScene == null)
            { 
                _curScene = actor.CurrentScene;
                if(!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id,out mPathFinder)) // Attempts to pull the pathfinder which matches the scenes SNO from the patherlist
                {
                    mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid); // Create a new pather, using the current scenes grid.
                    listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder); // add it to our patherlist, with the SNO as key.
                }
                
                InitPathFinder();
            }
            
            // Checks if our path start location is inside current scene, if it isnt, we reset curScene and set mPathfinder to the corrent grid.
            if (!_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Start.X, Start.Y, 1, 1)))
            { 
                _curScene = actor.CurrentScene;// TODO- THIS CAN RETURN PARENT RATHER THAN SUBSCENE - DarkLotus
                if (!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id, out mPathFinder))
                {
                    mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid);
                    listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder);
                }

                InitPathFinder();
            }

            _baseX = _curScene.Position.X; //Our base location for working out world > SceneLocal coordinates.
            _baseY = _curScene.Position.Y;

            // Path's start and destination are both in same scene.
            if (_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)))
            {
                _destScene = _curScene; 
            }
            else
            {
                //Builds a new grid on the fly containing both the start and destination scenes. This is not really optimal, but its a trade off.
                // Keeping grids Scene based means they can be used cross game even when laid out different in a seperate world. This keeps memory usage down substantially.
                // Also limited to a max distance of scene > scene. Again this keeps memory usage low.
                _destScene = _curScene.World.QuadTree.Query<Scene>(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)).FirstOrDefault();
                mPathFinder = new PathFinderFast(BuildOutOfSceneGrid(_curScene, _destScene, ref _baseX, ref _baseY));
                InitPathFinder();
            }
            //2.5f is because Scene navmesh's are based on 96x96 for a 240x240 scene - Darklotus
            _startSceneLocal.X = (int)((Start.X - _baseX) / 2.5f);
            _startSceneLocal.Y = (int)((Start.Y - _baseY) / 2.5f);
            _destinationSceneLocal.X = (int)((Destination.X - _baseX) / 2.5f);
            _destinationSceneLocal.Y = (int)((Destination.Y - _baseY) / 2.5f);
            //Possibily add a check to ensure start/dest local coords are valid. Unneeded so far.
            
            nodePathList = mPathFinder.FindPath(_startSceneLocal, _destinationSceneLocal); // The actual pathfind request, the path is found here.
            
            vectorPathList.Clear(); // Clear the previous path.

            if (nodePathList == null) {
                //TODO: Sometimes Mobs are require to spawn outside current walkable boundaries, with the current implementation
                //Pathfinder is unable to return a valid path if the mob is outside this boundaries.
                //This is just a hackish way to force a path over the mob.
                Logger.Debug("Pathfinding forced hack activated due Mob outside walkable area");
                vectorPathList.Insert(0, new Vector3D(Destination.X,Destination.Y,Destination.Z));
                return vectorPathList; 
                
            }// No Path Found.
            if (nodePathList.Count < 1) { return vectorPathList; } // Safety net Incase start/dest are the same.
           
            for (int i = 0; i < nodePathList.Count; i++)
            {
                // Convert the path into world coordinates for use in Movement.
                // TODO Objectpool maybe?
                vectorPathList.Insert(0, new Vector3D(nodePathList[i].X * 2.5f + _baseX, nodePathList[i].Y * 2.5f + _baseY, 0));
            }
            //new System.Threading.Thread(c => System.Windows.Forms.Application.Run(new PatherDebug.PatherDebug(actor, vectorPathList))).Start();
            
           
            return vectorPathList;
        }
예제 #2
0
            public List <Vector3D> FindPath(Actor actor, Vector3D Start, Vector3D Destination)
            {
                _baseX = 0; _baseY = 0; // reset to 0

                // Should only be null first time a path is requested.
                if (_curScene == null)
                {
                    _curScene = actor.CurrentScene;
                    if (!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id, out mPathFinder)) // Attempts to pull the pathfinder which matches the scenes SNO from the patherlist
                    {
                        mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid);                   // Create a new pather, using the current scenes grid.
                        listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder);           // add it to our patherlist, with the SNO as key.
                    }

                    InitPathFinder();
                }

                // Checks if our path start location is inside current scene, if it isnt, we reset curScene and set mPathfinder to the corrent grid.
                if (!_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Start.X, Start.Y, 1, 1)))
                {
                    _curScene = actor.CurrentScene;
                    if (!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id, out mPathFinder))
                    {
                        mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid);
                        listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder);
                    }

                    InitPathFinder();
                }

                _baseX = _curScene.Position.X; //Our base location for working out world > SceneLocal coordinates.
                _baseY = _curScene.Position.Y;

                // Path's start and destination are both in same scene.
                if (_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)))
                {
                    _destScene = _curScene;
                }
                else
                {
                    //Builds a new grid on the fly containing both the start and destination scenes. This is not really optimal, but its a trade off.
                    // Keeping grids Scene based means they can be used cross game even when laid out different in a seperate world. This keeps memory usage down substantially.
                    // Also limited to a max distance of scene > scene. Again this keeps memory usage low.
                    _destScene  = _curScene.World.QuadTree.Query <Scene>(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)).FirstOrDefault();
                    mPathFinder = new PathFinderFast(BuildOutOfSceneGrid(_curScene, _destScene, ref _baseX, ref _baseY));
                    InitPathFinder();
                }
                //2.5f is because Scene navmesh's are based on 96x96 for a 240x240 scene - Darklotus
                _startSceneLocal.X       = (int)((Start.X - _baseX) / 2.5f);
                _startSceneLocal.Y       = (int)((Start.Y - _baseY) / 2.5f);
                _destinationSceneLocal.X = (int)((Destination.X - _baseX) / 2.5f);
                _destinationSceneLocal.Y = (int)((Destination.Y - _baseY) / 2.5f);
                //Possibily add a check to ensure start/dest local coords are valid. Unneeded so far.

                nodePathList = mPathFinder.FindPath(_startSceneLocal, _destinationSceneLocal); // The actual pathfind request, the path is found here.

                vectorPathList.Clear();                                                        // Clear the previous path.

                if (nodePathList == null)
                {
                    return(vectorPathList);
                }                                                   // No Path Found.
                if (nodePathList.Count < 1)
                {
                    return(vectorPathList);
                }                                                      // Safety net Incase start/dest are the same.

                for (int i = 0; i < nodePathList.Count; i++)
                {
                    // Convert the path into world coordinates for use in Movement.
                    // TODO Objectpool maybe?
                    vectorPathList.Insert(0, new Vector3D(nodePathList[i].X * 2.5f + _baseX, nodePathList[i].Y * 2.5f + _baseY, 0));
                }
                return(vectorPathList);
            }