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 List _cells = new(), _leftmostColumn = new(), _rightmostColumn = new(), _topRow = new(), _bottomRow = new(); public AStarGrid2D _astar = new(); public Dictionary _addressOccupants = new(); public int _firstOpenRow { get { for (int i = 0; i < _maxY; i++) { if (!IsRowFull(i)) { return i; } } return -1; } } public int _lastOpenRow { get { for (int i = _maxY; i > _minY; i--) { if (!IsRowFull(i)) { return i; } } return -1; } } public int _firstOpenColumn { get { for (int i = 0; i < _maxX; i++) { if (!IsColumnnFull(i)) { return i; } } return -1; } } public int _lastOpenColumn { get { for (int i = _maxX; i > _minX; i--) { if (!IsColumnnFull(i)) { return i; } } return -1; } } 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 Peg 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 IsColumnnFull(int COLUMN_TO_CHECK) { List rowCells = [.. _cells.Where(c => c.X == COLUMN_TO_CHECK)]; return rowCells.All(c => _astar.IsPointSolid(c)); } 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 SetCellPeg(Vector2I ADDRESS, Peg PEG) { if (PEG != null) { if (PEG._address != -Vector2I.One) { _addressOccupants[PEG._address] = null; SetCellSolid(PEG._address); } PEG._address = ADDRESS; } _addressOccupants[ADDRESS] = PEG; 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(); for (int i = 0; i < _cells.Count; i++) { _astar.SetPointWeightScale(_cells[i], _cells[i].Y * 2); } EvaluateSolidCells(); } public List GetPath(Vector2I FROM, Vector2I TO, bool INCLUDE_FROM = false) { _astar.SetPointSolid(FROM, false); List pathTaken = [.. _astar.GetIdPath(FROM, TO)]; _astar.SetPointSolid(FROM, true); if (!INCLUDE_FROM) { pathTaken.Remove(FROM); } return pathTaken; } public void EvaluateSolidCells() { for (int i = 0; i < _cells.Count; i++) { SetCellSolid(_cells[i]); } } }