using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using StardewValley; using xTile.Layers; namespace Pathoschild.Stardew.Common { /// Provides extension methods for working with tiles. internal static class TileHelper { /********* ** Public methods *********/ /**** ** Location ****/ /// Get the tile coordinates in the game location. /// The game location to search. public static IEnumerable GetTiles(this GameLocation location) { if (location?.Map?.Layers == null) return Enumerable.Empty(); Layer layer = location.Map.Layers[0]; return TileHelper.GetTiles(0, 0, layer.LayerWidth, layer.LayerHeight); } /**** ** Rectangle ****/ /// Get the tile coordinates in the tile area. /// The tile area to search. public static IEnumerable GetTiles(this Rectangle area) { return TileHelper.GetTiles(area.X, area.Y, area.Width, area.Height); } /// Expand a rectangle equally in all directions. /// The rectangle to expand. /// The number of tiles to add in each direction. public static Rectangle Expand(this Rectangle area, int distance) { return new Rectangle(area.X - distance, area.Y - distance, area.Width + distance * 2, area.Height + distance * 2); } /**** ** Tiles ****/ /// Get the eight tiles surrounding the given tile. /// The center tile. public static IEnumerable GetSurroundingTiles(this Vector2 tile) { return Utility.getSurroundingTileLocationsArray(tile); } /// Get the tiles surrounding the given tile area. /// The center tile area. public static IEnumerable GetSurroundingTiles(this Rectangle area) { for (int x = area.X - 1; x <= area.X + area.Width; x++) { for (int y = area.Y - 1; y <= area.Y + area.Height; y++) { if (!area.Contains(x, y)) yield return new Vector2(x, y); } } } /// Get the four tiles adjacent to the given tile. /// The center tile. public static IEnumerable GetAdjacentTiles(this Vector2 tile) { return Utility.getAdjacentTileLocationsArray(tile); } /// Get a rectangular grid of tiles. /// The X coordinate of the top-left tile. /// The Y coordinate of the top-left tile. /// The grid width. /// The grid height. public static IEnumerable GetTiles(int x, int y, int width, int height) { for (int curX = x, maxX = x + width - 1; curX <= maxX; curX++) { for (int curY = y, maxY = y + height - 1; curY <= maxY; curY++) yield return new Vector2(curX, curY); } } /// Get all tiles which are on-screen. public static IEnumerable GetVisibleTiles() { return TileHelper.GetVisibleArea().GetTiles(); } /// Get the tile area visible on-screen. public static Rectangle GetVisibleArea() { return new Rectangle( x: Game1.viewport.X / Game1.tileSize, y: Game1.viewport.Y / Game1.tileSize, width: (int)(Game1.viewport.Width / (decimal)Game1.tileSize) + 2, // extend off-screen slightly to avoid edges popping in height: (int)(Game1.viewport.Height / (decimal)Game1.tileSize) + 2 ); } /**** ** Cursor ****/ /// Get the tile under the player's cursor (not restricted to the player's grab tile range). public static Vector2 GetTileFromCursor() { return TileHelper.GetTileFromScreenPosition(Game1.getMouseX(), Game1.getMouseY()); } /// Get the tile at the pixel coordinate relative to the top-left corner of the screen. /// The pixel X coordinate. /// The pixel Y coordinate. public static Vector2 GetTileFromScreenPosition(float x, float y) { return new Vector2((int)((Game1.viewport.X + x) / Game1.tileSize), (int)((Game1.viewport.Y + y) / Game1.tileSize)); } } }