using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading.Tasks; using ZoFo.GameCore.GameManagers.MapManager.MapElements; using ZoFo.GameCore.GameObjects; using ZoFo.GameCore.GameObjects.MapObjects; using ZoFo.GameCore.GameObjects.MapObjects.StopObjects; namespace ZoFo.GameCore.GameManagers.MapManager { public class MapManager { private static readonly string _templatePath = "Content/MapData/TileMaps/{0}.tmj"; private static readonly JsonSerializerOptions _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; // Задача настроек для JsonSerialize private static readonly Dictionary _classPath = new Dictionary() { { "Collectables", "ZoFo.GameCore.GameObjects.Entities.Interactables.Collectables." }, { "Enemies", "ZoFo.GameCore.GameObjects.Entities.LivingEntities.Enemies." } }; //private static readonly float _scale = 1.0f; private List _tileSets = new List(); private TileMap _tileMap = new TileMap(); /// /// Загрузка карты. Передаётся название файла карты. По умолчанию main. /// /// public void LoadMap(string mapName = "main") { // Загрузка TileMap _tileMap = JsonSerializer.Deserialize(File.ReadAllText(string.Format(_templatePath, mapName)), _options); // Загрузка TileSet-ов по TileSetInfo foreach (TileSetInfo tileSetInfo in _tileMap.TileSets) { TileSet tileSet = LoadTileSet(Path.Combine(AppContext.BaseDirectory, "Content", "MapData", "TileMaps", tileSetInfo.Source)); tileSet.FirstGid = tileSetInfo.FirstGid; _tileSets.Add(tileSet); } _tileSets.Reverse(); foreach (var layer in _tileMap.Layers) { if (layer.Type == "objectgroup") { ProcessObjectLayers(layer); } else { ProcessTileLayers(layer); } } } private void ProcessTileLayers(Layer layer) { foreach (var chunk in layer.Chunks) { for (int i = 0; i < chunk.Data.Length; i++) { foreach (var tileSet in _tileSets) { if (tileSet.FirstGid <= chunk.Data[i]) { int number = chunk.Data[i] - tileSet.FirstGid; int relativeColumn = number % tileSet.Columns; int relativeRow = number / tileSet.Columns; // относительно левого угла чанка Rectangle sourceRectangle = new Rectangle(relativeColumn * (tileSet.TileWidth + tileSet.Spacing) + tileSet.Margin, relativeRow * (tileSet.TileHeight + tileSet.Spacing) + tileSet.Margin, tileSet.TileWidth, tileSet.TileHeight); Vector2 position = new Vector2( (i % chunk.Width) * _tileMap.TileWidth + chunk.X * _tileMap.TileWidth, (i / chunk.Height) * _tileMap.TileHeight + chunk.Y * _tileMap.TileHeight); Tile tile = tileSet.Tiles[number]; // По факту может быть StopObjectom, но на уровне Tiled это все в первую очередь Tile switch (tile.Type) { case "Tile": AppManager.Instance.server.RegisterGameObject(new MapObject(position, new Vector2(tileSet.TileWidth, tileSet.TileHeight), sourceRectangle, "Textures/TileSetImages/" + Path.GetFileName(tileSet.Image).Replace(".png", ""))); break; case "StopObject": var collisionRectangles = LoadRectangles(tile); // Грузит коллизии обьектов AppManager.Instance.server.RegisterGameObject(new StopObject(position, new Vector2(tileSet.TileWidth, tileSet.TileHeight), sourceRectangle, "Textures/TileSetImages/" + Path.GetFileName(tileSet.Image).Replace(".png", ""), collisionRectangles.ToArray())); break; default: break; } break; } } } } } private void ProcessObjectLayers(Layer layer) { foreach (var item in layer.Objects) { string type = Path.GetFileName(item.Template).Replace(".tj", ""); var collectable = Activator.CreateInstance(Type.GetType(_classPath[layer.Name] + type), new Vector2(item.X, item.Y)); AppManager.Instance.server.RegisterGameObject(collectable as GameObject); } } /// /// Загружает и парсит TileSet по его пути. /// /// /// private TileSet LoadTileSet(string path) { return JsonSerializer.Deserialize(File.ReadAllText(path), _options); } /// /// Загружает все квадраты коллизии тайла. /// /// /// private List LoadRectangles(Tile tile) { if (tile.Objectgroup == null) { return new List() { new Rectangle(0, 0, 0, 0) }; } List collisionRectangles = new List(); foreach (var obj in tile.Objectgroup.Objects) { collisionRectangles.Add(new Rectangle((int)obj.X, (int)obj.Y, (int)obj.Width, (int)obj.Height)); } return collisionRectangles; } private MapElements.Object LoadObject(string path) { return JsonSerializer.Deserialize(File.ReadAllText(path), _options); } } }