using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using V3.Camera; namespace V3.Map { /// /// Tells the pathfinder where you can walk. /// public sealed class PathfindingGrid { private const int CellHeight = Constants.CellHeight; private const int CellWidth = Constants.CellWidth; private readonly bool[,] mArray; public readonly int mGridWidth; public readonly int mGridHeight; private Texture2D mTexture; private Texture2D mMinimapTexture; public PathfindingGrid(int mapWidth, int mapHeight, int tileWidth, int tileHeight) { mGridHeight = (mapHeight - 1) * tileHeight / CellHeight / 2; mGridWidth = (mapWidth - 1) * tileWidth / CellWidth; mArray = new bool[mGridHeight, mGridWidth]; } /// /// Compares the pathfinding grid with the given collision grid and adjusts the former. /// If a cell of the pathfinding grid is false and the cell at the same position of the /// collision grid is true, switch false to true. /// /// A grid of the same size as the pathfinding grid. public void CreateCollisions(bool[,] collisionGrid) { if (collisionGrid.Length == mGridWidth * mGridHeight) { for (int i = 0; i < mGridHeight; i++) { for (int j = 0; j < mGridWidth; j++) { if (!mArray[i, j]) { mArray[i, j] = collisionGrid[i, j]; } } } } else { throw new Exception("Error creating the collision grid. Object layer data and collision grid data do not fit."); } } /// /// Load content for visual representation of the pathfinding grid. /// /// Use this content manager. public void LoadContent(ContentManager contentManager) { mTexture = contentManager.Load("Textures/pathfinder"); //mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); } /// /// A visual representation of the pathfinding grid. Drawn efficiently. /// /// Sprite batch used for drawing. /// For only drawing on the shown part of the map. public void Draw(SpriteBatch spriteBatch, ICamera camera) { Point startPosition = camera.Location.ToPoint() / new Point(CellWidth, CellHeight); Point tilesOnScreen = camera.ScreenSize / new Point(CellWidth, CellHeight) + new Point(1, 1) + startPosition; for (int i = startPosition.Y; i < tilesOnScreen.Y && i < mGridHeight; i++) { for (int j = startPosition.X; j < tilesOnScreen.X && j < mGridWidth; j++) { Rectangle destinationRectangle = new Rectangle(j * CellWidth, i * CellHeight, CellWidth, CellHeight); Rectangle sourceRectangle = new Rectangle(mArray[i, j] ? CellWidth : 0, 0, CellWidth, CellHeight); spriteBatch.Draw(mTexture, destinationRectangle, sourceRectangle, Color.White); } } } /// /// Gets the value at the specified position of the collision array. /// /// Position at the horizontal axis. /// Position at the vertical axis. /// Returns 0 if you can walk at the specified position, 1 otherwise. public int GetIndex(int cellX, int cellY) { //if (cellX < 0 || cellX > mGridWidth - 1 || cellY < 0 || cellY > mGridHeight - 1) // return 0; return mArray[cellY, cellX] ? 1 : 0; } /// /// Draws a small version of the pathfinding grid to the screen. /// Useful for the minimap. /// /// Sprite batch used. /// Where to draw in pixel coordinates and which size. In pixels. public void DrawSmallGrid(SpriteBatch spriteBatch, Rectangle position) { spriteBatch.Draw(mMinimapTexture, position, Color.White); } public void CreateMinimap(GraphicsDevice device) { Color[] colors = new Color[mGridWidth * mGridHeight]; for (int i = 0; i < mGridHeight; i++) { for (int j = 0; j < mGridWidth; j++) { colors[i * mGridWidth + j ] = mArray[i, j] ? Color.DarkGray : Color.Green; } } mMinimapTexture = new Texture2D(device, mGridWidth, mGridHeight); mMinimapTexture.SetData(colors); } } }