Пример #1
0
        public static void AddConnection(Cell traceCur, Cell traceStart, NavMeshCell navCell)
        {
            if (traceCur == null || traceStart == null)
            {
                return;
            }

            // Determine which side the connected cell is on.
            // Generate edge at opposite side.
            Vector2 center;

            if (traceCur.Mid.X > navCell.CollisionRect.Right) // East
            {
                center = (traceStart.CollisionRect.CenterLeft() + traceCur.CollisionRect.CenterLeft()) / 2;
            }
            else if (traceCur.Mid.X < navCell.CollisionRect.Left) // West
            {
                center = (traceStart.CollisionRect.CenterRight() + traceCur.CollisionRect.CenterRight()) / 2;
            }
            else if (traceCur.Mid.Y < navCell.CollisionRect.Top) // North
            {
                center = (traceStart.CollisionRect.CenterBottom() + traceCur.CollisionRect.CenterBottom()) / 2;
            }
            else // South
            {
                center = (traceStart.CollisionRect.CenterTop() + traceCur.CollisionRect.CenterTop()) / 2;
            }

            NavMeshCell other = navCells[(int)traceStart.MeshID - 1];

            navCell.Neighbours.Add(other);
            navCell.Waypoints.Add(other, center);
        }
Пример #2
0
        private static List <Cell> GetNextNorthRow(NavMeshCell curCell)
        {
            var result = new List <Cell>();

            Point topLeft = Grid.IndexAt(new Vector2(curCell.Pos.X, curCell.Pos.Y - 1));
            int   numCols = curCell.Width / Grid.CellSize;

            for (int i = 0; i < numCols; i++)
            {
                Grid.AddCell(Grid[topLeft.Col() + i, topLeft.Row()], result);
            }

            return(result);
        }
Пример #3
0
        private static List <Cell> GetNextWestCol(NavMeshCell curCell)
        {
            var result = new List <Cell>();

            Point topLeft = Grid.IndexAt(new Vector2(curCell.Pos.X - 1, curCell.Pos.Y));
            int   numRows = curCell.Height / Grid.CellSize;

            for (int i = 0; i < numRows; i++)
            {
                Grid.AddCell(Grid[topLeft.Col(), topLeft.Row() + i], result);
            }

            return(result);
        }
Пример #4
0
 private static List <Cell> GetNextBorder(NavMeshCell curCell)
 {
     return(GetNextEastCol(curCell).Concat(GetNextSouthRow(curCell)).Concat(GetNextWestCol(curCell)).Concat(GetNextNorthRow(curCell)).ToList());
 }
Пример #5
0
        public static void RenderNavMeshCalculation(Point startCellAtIndex,
                                                    NavMeshCell curNavCell,
                                                    bool blockedOnCols,
                                                    bool blockedOnRows,
                                                    List <Cell> toBeConsidered,
                                                    List <Cell> frontier,
                                                    Cell traceStart,
                                                    Cell traceCur)
        {
            if (!Debug.IsOn(DebugOp.CalcNavMesh))
            {
                return;
            }

            SpriteBatch spriteBatch = Game1.Instance.spriteBatch;


            Input.UpdateStates();
            Game1.Instance.GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            Game1.Instance.world.Render(spriteBatch);

            // Render already constructed nav cells dark blue.
            foreach (NavMeshCell cell in navCells)
            {
                spriteBatch.DrawRectangle(cell.RenderRect, Color.DarkBlue, 2);
            }

            // Render currently being constructed nav cell pink
            spriteBatch.FillRectangle(curNavCell.RenderRect, Color.Pink);

            // Render current location to start new nav cell
            spriteBatch.FillRectangle(Grid[startCellAtIndex].RenderRect, Color.Teal);

            // Render frontier brown
            foreach (Cell c in frontier)
            {
                spriteBatch.FillRectangle(c.RenderRect, Color.Brown);
            }

            // Render new cells to be considered in yellow
            foreach (Cell c in toBeConsidered)
            {
                spriteBatch.FillRectangle(c.RenderRect, Color.Yellow);
            }

            // Render neighbours white
            foreach (NavMeshCell navCell in navCells)
            {
                foreach (Vector2 pos in navCell.Waypoints.Values)
                {
                    spriteBatch.DrawLine(navCell.RenderMid, pos, Color.White, 1);
                }

                spriteBatch.DrawPoint(navCell.RenderMid, Color.Orange, 6);
            }

            // Render trace.
            if (traceStart != null)
            {
                spriteBatch.FillRectangle(traceStart.RenderRect, Color.DarkViolet);
            }

            if (traceCur != null)
            {
                spriteBatch.FillRectangle(traceCur.RenderRect, Color.DarkViolet);
            }

            if (traceStart != null && traceCur != null)
            {
                spriteBatch.DrawLine(traceStart.RenderMid, traceCur.RenderMid, Color.Red, 3);
            }

            foreach (NavMeshCell cell in navCells)
            {
                Game1.Instance.spriteBatch.DrawString(Game1.Instance.smallFont, cell.NavMeshID.ToString(), cell.RenderMid, Color.Black);
            }

            Game1.Instance.spriteBatch.End();
            Game1.Instance.GraphicsDevice.Present();

            //System.Threading.Thread.Sleep(400);
        }
Пример #6
0
 private static void AddNavCell(NavMeshCell cell)
 {
     navCells.Add(cell);
     navCells = navCells.OrderBy(c => c.NavMeshID).ToList();
 }
Пример #7
0
        public static List <NavMeshCell> CalculateNavMeshCells(Grid grid)
        {
            NavMeshCell.ResetMeshIDs();
            Grid = grid;

            for (int col = 0; col < Grid.Cols; col++)
            {
                for (int row = 0; row < Grid.Rows; row++)
                {
                    Grid[col, row].MeshID = Cell.NOT_PART_OF_MESH;
                }
            }

            startAt = new Point(Grid.Cols / 2, Grid.Rows / 2);
            Grid[startAt].Passable = true;
            //startAt = new Point(0, 0);
            finishedCalculating = false;
            blockedEast         = false;
            blockedSouth        = false;
            blockedWest         = false;
            blockedNorth        = false;

            navCells = new List <NavMeshCell>();
            curCell  = new NavMeshCell(Grid[startAt].Pos, Grid.CellSize, Grid.CellSize);
            frontier = new List <Cell>();

            while (!finishedCalculating)
            {
                // If cell is becoming long and skinny, restrict expansion on that axis.

                // Restrict East / West expansion
                if (curCell.Width >= curCell.Height * 3)
                {
                    blockedEast = true;
                    blockedWest = true;
                }

                // Restrict North / South expansion
                if (curCell.Height >= curCell.Width * 3)
                {
                    blockedNorth = true;
                    blockedSouth = true;
                }

                // Try to expand east.
                if (!blockedEast)
                {
                    blockedEast = DoNewCellsBlock(GetNextEastCol(curCell));

                    // Expansion is valid.
                    if (!blockedEast)
                    {
                        // Increase size of current cell.
                        curCell.Width += Grid.CellSize;
                    }
                }

                // Try to expand south.
                if (!blockedSouth)
                {
                    blockedSouth = DoNewCellsBlock(GetNextSouthRow(curCell));

                    // Expansion is valid
                    if (!blockedSouth)
                    {
                        // Increase size of current cell.
                        curCell.Height += Grid.CellSize;
                    }
                }

                // Try to expand west.
                if (!blockedWest)
                {
                    blockedWest = DoNewCellsBlock(GetNextWestCol(curCell));

                    // Expansion is valid
                    if (!blockedWest)
                    {
                        // Increase size of current cell.
                        curCell.Width += Grid.CellSize;
                        curCell.Pos.X -= Grid.CellSize;
                    }
                }

                // Try to expand north.
                if (!blockedNorth)
                {
                    blockedNorth = DoNewCellsBlock(GetNextNorthRow(curCell));

                    // Expansion is valid.
                    if (!blockedNorth)
                    {
                        // Increase size of current cell.
                        curCell.Height += Grid.CellSize;
                        curCell.Pos.Y  -= Grid.CellSize;
                    }
                }

                // Blocked on both dimensinos, finalise this nav mesh cell.
                if (BlockedOnAllSides)
                {
                    // Finish making this cell and start making a new one.
                    // Probably calculate neighbours here too.
                    uint nextMeshID = NavMeshCell.NextMeshID;
                    curCell.NavMeshID = nextMeshID;
                    AddNavCell(curCell);

                    // Assign each cell in the area as part of the new Nav Mesh Cell.
                    foreach (Cell c in Grid.CellsInRect(curCell.CollisionRect.GetInflated(-1, -1)))
                    {
                        c.MeshID = nextMeshID;
                    }

                    // Update frontier to remove any cells now part of the mesh
                    for (int i = frontier.Count - 1; i >= 0; i--)
                    {
                        if (frontier[i].MeshID != Cell.NOT_PART_OF_MESH)
                        {
                            frontier.RemoveAt(i);
                        }
                    }

                    // Get surrounding cells.
                    var newCells = GetNextBorder(curCell);

                    foreach (Cell c in newCells)
                    {
                        // Add to frontier if valid
                        if (c.Passable && c.MeshID == Cell.NOT_PART_OF_MESH)
                        {
                            frontier.Add(c);
                        }
                    }

                    if (frontier.Count == 0)
                    {
                        finishedCalculating = true;
                    }

                    if (!finishedCalculating)
                    {
                        startAt      = Grid.IndexAt(frontier[0].Mid);
                        curCell      = new NavMeshCell(Grid[startAt].Pos, Grid.CellSize, Grid.CellSize);
                        blockedEast  = false;
                        blockedSouth = false;
                        blockedNorth = false;
                        blockedWest  = false;
                    }
                }
            }

            CalculateNeighbours();
            return(navCells);
        }