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));
}
}
}