using Godot; using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; public partial class Map : TileMapLayer { public int _minX, _maxX, _minY, _maxY, _mainSource = 0; public string _isSolidString = "is_solid"; public Vector2 _cellSize, _sizeInPixels, _sizeInCells; public Vector2I _pathTakenAtlasCoordinates = new Vector2I(4, 0); public List _cells = new(), _leftmostColumn = new(), _rightmostColumn = new(), _topRow = new(), _bottomRow = new(); public AStarGrid2D _astar = new(); public Dictionary _addressOccupants = new(); public override void _Ready() { base._Ready(); _cellSize = TileSet.TileSize; _cells = [.. GetUsedCells()]; _cells.ForEach(c => _addressOccupants[c] = null); _minX = _cells.Min(c => c.X); _maxX = _cells.Max(c => c.X); _minY = _cells.Min(c => c.Y); _maxY = _cells.Max(c => c.Y); _leftmostColumn = [.. _cells.Where(c => c.X == _minX)]; _rightmostColumn = [.. _cells.Where(c => c.X == _maxX)]; _topRow = [.. _cells.Where(c => c.Y == _minY)]; _bottomRow = [.. _cells.Where(c => c.Y == _maxY)]; _sizeInCells = new Vector2(_topRow.Count, _leftmostColumn.Count); _sizeInPixels = _sizeInCells * _cellSize; SetupAstar(); } public Vector2I GetAddressFromPosition(Vector2 POSITION) { if (POSITION.X < GlobalPosition.X || POSITION.Y < GlobalPosition.Y) { return new Vector2I(-1,-1); } else if (POSITION.X > (GlobalPosition + (new Vector2(_maxX, _maxY) * _cellSize)).X || POSITION.Y > (GlobalPosition + (new Vector2(_maxX, _maxY) * _cellSize)).Y) { return new Vector2I(-1,-1); } return new Vector2I((int)Math.Floor(POSITION.X / _cellSize.X), (int)Math.Floor(POSITION.Y / _cellSize.Y)); } public Vector2 GetCellPositionFromAddress(Vector2I CELL_ADDRESS) { return GlobalPosition + CELL_ADDRESS * _cellSize + _cellSize / 2; } public int GetFirstOpenRow() { for (int i = 0; i < _maxY; i++) { if (!IsRowFull(i)) { return i; } } return 1; } public Enemy GetOccupant(Vector2I CELL_TO_CHECK) { return _addressOccupants[CELL_TO_CHECK]; } public bool HasOccupant(Vector2I CELL_TO_CHECK) { return GetOccupant(CELL_TO_CHECK) != null; } public bool IsCellSolid(Vector2I CELL_TO_CHECK) { bool hasOccupant = HasOccupant(CELL_TO_CHECK); bool isSolid = (bool)GetCellTileData(CELL_TO_CHECK).GetCustomData(_isSolidString); return hasOccupant || isSolid; } public bool IsRowFull(int ROW_TO_CHECK) { List rowCells = [.. _cells.Where(c => c.Y == ROW_TO_CHECK)]; return rowCells.All(c => _astar.IsPointSolid(c)); } public void SetCellEnemy(Vector2I ADDRESS, Enemy ENEMY) { _addressOccupants[ENEMY._address] = null; SetCellSolid(ENEMY._address); ENEMY._address = ADDRESS; _addressOccupants[ADDRESS] = ENEMY; SetCellSolid(ADDRESS); } public void SetCellSolid(Vector2I ADDRESS) { _astar.SetPointSolid(ADDRESS, IsCellSolid(ADDRESS)); // _astar.SetPointWeightScale(ADDRESS, IsCellSolid(ADDRESS) ? 1000 : 1); } public void SetupAstar() { _astar.Region = new Rect2I(_minX, _minY, _topRow.Count, _leftmostColumn.Count); _astar.CellSize = _cellSize; _astar.DefaultComputeHeuristic = AStarGrid2D.Heuristic.Manhattan; _astar.DiagonalMode = AStarGrid2D.DiagonalModeEnum.Never; _astar.Update(); EvaluateSolidCells(); } public List GetPath(Vector2I FROM, Vector2I TO, bool INCLUDE_FROM = false) { _astar.SetPointSolid(FROM, false); if (FROM == Vector2I.Zero) { GD.Print(4,_astar.IsPointSolid(FROM)); } if (TO == Vector2I.Zero) { GD.Print(5,_astar.IsPointSolid(FROM)); } List pathTaken = [.. _astar.GetIdPath(FROM, TO, true)]; _astar.SetPointSolid(FROM, true); if (FROM == Vector2I.Zero) { GD.Print(6,_astar.IsPointSolid(FROM)); } if (TO == Vector2I.Zero) { GD.Print(7,_astar.IsPointSolid(FROM)); } if (!INCLUDE_FROM) { pathTaken.Remove(FROM); } return pathTaken; } public void EvaluateSolidCells() { for (int i = 0; i < _cells.Count; i++) { SetCellSolid(_cells[i]); } } }