| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- using System;
- using System.Collections.Generic;
- using Microsoft.Xna.Framework;
- using MonoGame.Extended.Tiled;
- namespace MonoGame.Extended.Tilemaps
- {
- /// <summary>
- /// Represents a tilemap loaded from any supported format.
- /// </summary>
- /// <remarks>
- /// A tilemap is a collection of layers organized into a grid-based structure.
- /// Layers can contain tiles, objects, or images, and support various rendering
- /// features like parallax scrolling, opacity, and tinting.
- /// </remarks>
- public class Tilemap
- {
- /// <summary>
- /// Gets or sets the name of the tilemap.
- /// </summary>
- public string Name { get; set; }
- /// <summary>
- /// Gets the width of the tilemap in tiles.
- /// </summary>
- public int Width { get; }
- /// <summary>
- /// Gets the height of the tilemap in tiles.
- /// </summary>
- public int Height { get; }
- /// <summary>
- /// Gets the width of each tile in pixels.
- /// </summary>
- public int TileWidth { get; }
- /// <summary>
- /// Gets the height of each tile in pixels.
- /// </summary>
- public int TileHeight { get; }
- /// <summary>
- /// Gets the orientation of the tilemap.
- /// </summary>
- public TilemapOrientation Orientation { get; }
- /// <summary>
- /// Gets or sets the background color of the tilemap.
- /// </summary>
- public Color? BackgroundColor { get; set; }
- /// <summary>
- /// Gets the custom properties of the tilemap.
- /// </summary>
- public TilemapProperties Properties { get; }
- /// <summary>
- /// Gets the collection of tilesets used by this tilemap.
- /// </summary>
- public TilemapTilesetCollection Tilesets { get; }
- /// <summary>
- /// Gets the collection of layers in this tilemap.
- /// </summary>
- public TilemapLayerCollection Layers { get; }
- /// <summary>
- /// Gets the world-space bounds of the tilemap.
- /// </summary>
- public Rectangle WorldBounds
- {
- get
- {
- // For orthogonal maps, bounds are straightforward
- // For isometric/hexagonal maps, this is an axis-aligned bounding box
- return Orientation switch
- {
- TilemapOrientation.Orthogonal => new Rectangle(0, 0, Width * TileWidth, Height * TileHeight),
- // Isometric maps have a diamond shape, so we need to calculate the AABB
- TilemapOrientation.Isometric => CalculateIsometricBounds(),
- // For staggered and hexagonal, use orthogonal approximation for now
- // TODO: Implement precise bounds for staggered/hexagonal in future
- TilemapOrientation.Staggered => new Rectangle(0, 0, Width * TileWidth, Height * TileHeight),
- TilemapOrientation.Hexagonal => new Rectangle(0, 0, Width * TileWidth, Height * TileHeight),
- _ => new Rectangle(0, 0, Width * TileWidth, Height * TileHeight)
- };
- }
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="Tilemap"/> class.
- /// </summary>
- /// <param name="name">The name of the tilemap.</param>
- /// <param name="width">The width of the tilemap in tiles.</param>
- /// <param name="height">The height of the tilemap in tiles.</param>
- /// <param name="tileWidth">The width of each tile in pixels.</param>
- /// <param name="tileHeight">The height of each tile in pixels.</param>
- /// <param name="orientation">The orientation of the tilemap.</param>
- public Tilemap(string name, int width, int height, int tileWidth, int tileHeight, TilemapOrientation orientation)
- {
- Name = name;
- Width = width;
- Height = height;
- TileWidth = tileWidth;
- TileHeight = tileHeight;
- Orientation = orientation;
- Properties = new TilemapProperties();
- Tilesets = new TilemapTilesetCollection();
- Layers = new TilemapLayerCollection();
- }
- /// <summary>
- /// Converts tile coordinates to world-space position.
- /// </summary>
- /// <param name="x">The tile X coordinate.</param>
- /// <param name="y">The tile Y coordinate.</param>
- /// <returns>The position in world space, where (0,0) represents the top-left corner of the map.</returns>
- /// <remarks>
- /// This transformation accounts for the map's orientation and tile dimensions.
- /// For isometric maps, the calculation differs from orthogonal maps.
- /// </remarks>
- public Point TileToWorldPosition(int x, int y)
- {
- return Orientation switch
- {
- TilemapOrientation.Orthogonal => TileToWorldOrthogonal(x, y),
- TilemapOrientation.Isometric => TileToWorldIsometric(x, y),
- TilemapOrientation.Staggered => TileToWorldStaggered(x, y),
- TilemapOrientation.Hexagonal => TileToWorldHexagonal(x, y),
- _ => TileToWorldOrthogonal(x, y)
- };
- }
- /// <summary>
- /// Converts world-space position to tile coordinates.
- /// </summary>
- /// <param name="worldPosition">The position in world space.</param>
- /// <returns>The tile coordinates.</returns>
- public Point WorldToTilePosition(Vector2 worldPosition)
- {
- return Orientation switch
- {
- TilemapOrientation.Orthogonal => WorldToTileOrthogonal(worldPosition),
- TilemapOrientation.Isometric => WorldToTileIsometric(worldPosition),
- TilemapOrientation.Staggered => WorldToTileStaggered(worldPosition),
- TilemapOrientation.Hexagonal => WorldToTileHexagonal(worldPosition),
- _ => WorldToTileOrthogonal(worldPosition),
- };
- }
- #region Helper Methods
- private Rectangle CalculateIsometricBounds()
- {
- // Isometric maps form a diamond shape
- // The width and height in world space are:
- // width = (mapWidth * mapHeight) * (tileWidth / 2)
- // height = (mapWidth * mapHeight) * (tileHeight / 2)
- int worldWidth = (Width + Height) * (TileWidth / 2);
- int worldHeight = (Width + Height) * (TileHeight / 2);
- return new Rectangle(0, 0, worldWidth, worldHeight);
- }
- private Point TileToWorldOrthogonal(int x, int y)
- {
- return new Point(x * TileWidth, y * TileHeight);
- }
- private Point TileToWorldIsometric(int x, int y)
- {
- // Isometric transformation:
- // worldX = (x - y) * (tileWidth / 2)
- // worldY = (x + y) * (tileHeight / 2)
- int worldX = (x - y) * (TileWidth / 2);
- int worldY = (x + y) * (TileHeight / 2);
- return new Point(worldX, worldY);
- }
- private Point TileToWorldStaggered(int x, int y)
- {
- // TODO: Implement staggered transformation in future
- // For now, use orthogonal as approximation
- return TileToWorldOrthogonal(x, y);
- }
- private Point TileToWorldHexagonal(int x, int y)
- {
- // TODO: Implement hexagonal transformation in future
- // For now, use orthogonal as approximation
- return TileToWorldOrthogonal(x, y);
- }
- private Point WorldToTileOrthogonal(Vector2 worldPosition)
- {
- int tileX = (int)(worldPosition.X / TileWidth);
- int tileY = (int)(worldPosition.Y / TileHeight);
- return new Point(tileX, tileY);
- }
- private Point WorldToTileIsometric(Vector2 worldPosition)
- {
- // Inverse isometric transformation:
- // x = (worldX / (tileWidth/2) + worldY / (tileHeight/2)) / 2
- // y = (worldY / (tileHeight/2) - worldX / (tileWidth/2)) / 2
- float halfTileWidth = TileWidth * 0.5f;
- float halfTileHeight = TileHeight * 0.5f;
- float normalizedX = worldPosition.X / halfTileWidth;
- float normalizedY = worldPosition.Y / halfTileHeight;
- int tileX = (int)((normalizedX + normalizedY) * 0.5f);
- int tileY = (int)((normalizedY - normalizedX) * 0.5f);
- return new Point(tileX, tileY);
- }
- private Point WorldToTileStaggered(Vector2 worldPosition)
- {
- // TODO: Implement staggered transformation in future
- // For now, use orthogonal as approximation
- return WorldToTileOrthogonal(worldPosition);
- }
- private Point WorldToTileHexagonal(Vector2 worldPosition)
- {
- // TODO: Implement hexagonal transformation in future
- // For now, use orthogonal as approximation
- return WorldToTileOrthogonal(worldPosition);
- }
- #endregion
- }
- }
|