From 648a00ccf18dbabfe725d019e2d0c26e29b84dd9 Mon Sep 17 00:00:00 2001 From: cojoedmo Date: Mon, 8 Jun 2026 03:38:33 -0400 Subject: [PATCH] still working on some pathfinding, it is seizing up when trying to find a new goal --- EnemyController.cs | 76 ++++++++++++++++++++++------------------ Map.cs | 86 +++++++++++++++++++++++++++++----------------- PlayArea.tscn | 7 ++-- 3 files changed, 99 insertions(+), 70 deletions(-) diff --git a/EnemyController.cs b/EnemyController.cs index e195ce4..97848b7 100644 --- a/EnemyController.cs +++ b/EnemyController.cs @@ -22,7 +22,7 @@ public partial class EnemyController : TurnController newEnemy._enemyController = this; List unoccupied = [.. _playArea._map._bottomRow.Where(c => _enemies.All(e => e._address != c))]; Vector2I randomCell = unoccupied[Globals._rng.Next(unoccupied.Count)]; - WarpEnemy(newEnemy, randomCell); + SetEnemy(newEnemy, randomCell); _enemies.Add(newEnemy); AddChild(newEnemy); } @@ -39,7 +39,7 @@ public partial class EnemyController : TurnController newEnemy.Modulate = new Color(newEnemy._speed == 2 ? "#FF0000" : newEnemy._speed == 3 ? "#00FF00" : "#0000FF"); newEnemy._enemyController = this; - WarpEnemy(newEnemy, POSITIONS[i]); + SetEnemy(newEnemy, POSITIONS[i]); _enemies.Add(newEnemy); AddChild(newEnemy); } @@ -51,6 +51,15 @@ public partial class EnemyController : TurnController List positions = [.. _playArea.GetNode("InitialPositions").GetUsedCells()]; AddEnemies(positions); + + + // for (int i = 0; i < _playArea._map._cells.Count; i++) + // { + // if (_playArea._map._astar.IsPointSolid(_playArea._map._cells[i])) + // { + // GD.Print(_playArea._map._cells[i]); + // } + // } } public void MoveEnemies() @@ -61,27 +70,20 @@ public partial class EnemyController : TurnController for (int i = 0; i < _enemies.Count; i++) { Enemy enemy = _enemies[i]; - Vector2I goal = new(enemy._address.X, _playArea._map._minY); - if (Math.Abs(goal.Y - enemy._address.Y) <= enemy._visibilityRange) + Vector2I goal = new(enemy._address.X, Math.Max(enemy._address.Y - enemy._visibilityRange, _playArea._map._minY)); + + while(_playArea._map.IsRowFull(goal.Y)) { - // GD.Print(goal.Y, enemy._address.Y,enemy._visibilityRange); - while(_playArea._map.IsRowFull(goal.Y)) - { - goal.Y++; - } - // if (_playArea._map.GetOccupant(goal) != null) - // { - // goal.X = Math.Clamp(goal.X+1, _playArea._map._minX+1, _playArea._map._maxX-1); - // } - int loop = 0; - while (_playArea._map.GetOccupant(goal) != null) - { - goal.X = Math.Clamp(enemy._address.X + ((int)MathF.Floor(loop / 2) + 1) * (loop % 2 == 0 ? 1 : -1), _playArea._map._minX, _playArea._map._maxX); - loop++; - } + goal.Y++; } - List path = _playArea._map.GetPath(enemy._address, goal); - enemy._path = path; + int loop = 0; + while (_playArea._map.GetOccupant(goal) != null) + { + goal.X = Math.Clamp(enemy._address.X + ((int)MathF.Floor(loop / 2) + 1) * (loop % 2 == 0 ? 1 : -1), _playArea._map._minX, _playArea._map._maxX); + loop++; + } + + enemy._path = _playArea._map.GetPath(enemy._address, goal, false, i==0); enemy._speedRemaining = enemy._address.Y <= _playArea._map._minY ? 0 : enemy._speed; } _enemies = [.. _enemies.OrderByDescending(e => e._path.Count).ThenBy(e => e._address.Y).ThenBy(e => Math.Abs(e._address.X))]; @@ -99,17 +101,29 @@ public partial class EnemyController : TurnController remainingEnemies.Remove(enemy); continue; } - List path = enemy._path; + int pathIndex = enemy._speed - enemy._speedRemaining; - Vector2I cell = path[pathIndex]; + Vector2I cell = enemy._path[pathIndex]; Enemy obstacle = _playArea._map.GetOccupant(cell); if (obstacle != null) { int obstacleRemainingMoves = obstacle._speedRemaining; if (obstacleRemainingMoves <= 0) { - _playArea._map.EvaluateSolidCells(); - List newPath = _playArea._map.GetPath(enemy._address, new Vector2I(enemy._address.X, _playArea._map._minY)); + Vector2I newGoal = new(enemy._address.X, Math.Max(enemy._address.Y - enemy._visibilityRange, _playArea._map._minY)); + + while(_playArea._map.IsRowFull(newGoal.Y)) + { + newGoal.Y++; + } + int loop = 0; + while (_playArea._map.GetOccupant(newGoal) != null) + { + newGoal.X = Math.Clamp(enemy._address.X + ((int)MathF.Floor(loop / 2) + 1) * (loop % 2 == 0 ? 1 : -1), _playArea._map._minX, _playArea._map._maxX); + loop++; + } + List newPath = _playArea._map.GetPath(enemy._address, newGoal); + enemy._path = newPath; newPath.InsertRange(0, [.. Enumerable.Repeat(newPath[0], pathIndex)]); @@ -121,9 +135,7 @@ public partial class EnemyController : TurnController if (obstacle == null) { - _playArea._map.SetCellEnemy(enemy._address, null); - enemy._address = cell; - _playArea._map.SetCellEnemy(enemy._address, enemy); + _playArea._map.SetCellEnemy(cell, enemy); if (j == 0) { tween.Chain(); @@ -162,13 +174,9 @@ public partial class EnemyController : TurnController } - public void WarpEnemy(Enemy ENEMY, Vector2I CELL) + public void SetEnemy(Enemy ENEMY, Vector2I CELL) { - - _playArea._map.SetCellEnemy(ENEMY._address, null); - ENEMY._address = CELL; - - _playArea._map.SetCellEnemy(ENEMY._address, ENEMY); + _playArea._map.SetCellEnemy(CELL, ENEMY); ENEMY.GlobalPosition = _playArea._map.GetCellPositionFromAddress(CELL); } } diff --git a/Map.cs b/Map.cs index 75f87f3..9b8f3fc 100644 --- a/Map.cs +++ b/Map.cs @@ -9,7 +9,7 @@ public partial class Map : TileMapLayer public string _isSolidString = "is_solid"; public Vector2 _cellSize, _sizeInPixels, _sizeInCells; public Vector2I _pathTakenAtlasCoordinates = new Vector2I(4, 0); - public List _leftmostColumn, _rightmostColumn, _topRow, _bottomRow; + public List _cells = new(), _leftmostColumn = new(), _rightmostColumn = new(), _topRow = new(), _bottomRow = new(); public AStarGrid2D _astar = new(); public Dictionary _addressOccupants = new(); @@ -17,17 +17,16 @@ public partial class Map : TileMapLayer { base._Ready(); _cellSize = TileSet.TileSize; - List cells = [.. GetUsedCells()]; - _minX = cells.Min(c => c.X); - _maxX = cells.Max(c => c.X); - _minY = cells.Min(c => c.Y); - _maxY = cells.Max(c => c.Y); - // GD.Print(_minX, _maxX, _minY, _maxY); - _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)]; - cells.ForEach(c => SetCellEnemy(c, null)); + _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; @@ -48,49 +47,69 @@ public partial class Map : TileMapLayer public bool IsCellSolid(Vector2I CELL_TO_CHECK) { bool hasOccupant = GetOccupant(CELL_TO_CHECK) != null; + if (hasOccupant) + { + // GD.Print(CELL_TO_CHECK, " has occupant"); + } bool isSolid = (bool)GetCellTileData(CELL_TO_CHECK).GetCustomData(_isSolidString); + if (isSolid) + { + // GD.Print(CELL_TO_CHECK, " is solid"); + } return hasOccupant || isSolid; } public bool IsRowFull(int ROW_TO_CHECK) { - List cells = [.. GetUsedCells()]; - List rowCells = [.. cells.Where(c => c.Y == ROW_TO_CHECK)]; + List rowCells = [.. _cells.Where(c => c.Y == ROW_TO_CHECK)]; return rowCells.All(c => GetOccupant(c) != null); } public void SetCellEnemy(Vector2I ADDRESS, Enemy ENEMY) { + if (ENEMY != null) + { + if (ENEMY._address != -(Vector2I)Vector2.Inf) + { + _addressOccupants[ENEMY._address] = null; + } + ENEMY._address = ADDRESS; + } + _addressOccupants[ADDRESS] = ENEMY; - IsCellSolid(ADDRESS); + + SetCellSolid(ADDRESS); + + } + + public void SetCellSolid(Vector2I ADDRESS) + { + _astar.SetPointSolid(ADDRESS, IsCellSolid(ADDRESS)); } public void SetupAstar() { _astar.Region = new Rect2I(_minX, _minY, _topRow.Count, _leftmostColumn.Count); _astar.CellSize = _cellSize; - _astar.DefaultComputeHeuristic = AStarGrid2D.Heuristic.Manhattan; + _astar.DefaultComputeHeuristic = AStarGrid2D.Heuristic.Euclidean; _astar.DiagonalMode = AStarGrid2D.DiagonalModeEnum.Never; _astar.Update(); - List cells = [.. GetUsedCells()]; - for (int i = 0; i < cells.Count; i++) - { - _astar.SetPointSolid(cells[i], IsCellSolid(cells[i])); - } + EvaluateSolidCells(); } public List GetPath(Vector2I FROM, Vector2I TO, bool INCLUDE_FROM = false, bool SHOW_PATH = false) { - List pathTaken = [.. _astar.GetIdPath(FROM, TO)]; - if (SHOW_PATH) - { - for (int i = 0; i < pathTaken.Count; i++) - { - Vector2I cell = pathTaken[i]; - SetCell(cell, _mainSource, _pathTakenAtlasCoordinates); - } - } + _astar.SetPointSolid(FROM, false); + List pathTaken = [.. _astar.GetIdPath(FROM, TO, true)]; + // if (SHOW_PATH) + // { + // for (int i = 0; i < pathTaken.Count; i++) + // { + // Vector2I cell = pathTaken[i]; + // SetCell(cell, _mainSource, _pathTakenAtlasCoordinates); + // } + // } if (!INCLUDE_FROM) { pathTaken.Remove(FROM); @@ -99,8 +118,11 @@ public partial class Map : TileMapLayer } public void EvaluateSolidCells() - { - GetUsedCells().ToList().ForEach(c => IsCellSolid(c)); + { + for (int i = 0; i < _cells.Count; i++) + { + SetCellSolid(_cells[i]); + } } } diff --git a/PlayArea.tscn b/PlayArea.tscn index cb901b8..2598d0d 100644 --- a/PlayArea.tscn +++ b/PlayArea.tscn @@ -1,7 +1,7 @@ [gd_scene format=4 uid="uid://dumcridek4xy3"] [ext_resource type="Script" uid="uid://bnaxgcafcvtfv" path="res://PlayArea.cs" id="1_lq4m8"] -[ext_resource type="PackedScene" path="res://Map.tscn" id="2_wqv88"] +[ext_resource type="PackedScene" uid="uid://mjinvqj25wha" path="res://Map.tscn" id="2_wqv88"] [ext_resource type="Texture2D" uid="uid://cf554xlykq1o4" path="res://Art/tile_set.png" id="3_md2b6"] [ext_resource type="PackedScene" uid="uid://b2mb7mimdu5ad" path="res://bucket.tscn" id="5_vqhsw"] @@ -14,7 +14,7 @@ size = Vector2(400, 1000) [sub_resource type="RectangleShape2D" id="RectangleShape2D_7h2rc"] size = Vector2(400, 80) -[sub_resource type="TileMapPattern" id="TileMapPattern_xy0lb"] +[sub_resource type="TileMapPattern" id="TileMapPattern_vqhsw"] tile_data = PackedInt32Array(0, 0, 0, 65536, 0, 1, 1, 0, 1, 65537, 0, 0) [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vqhsw"] @@ -38,7 +38,7 @@ tile_size = Vector2i(40, 40) custom_data_layer_0/name = "is_solid" custom_data_layer_0/type = 1 sources/0 = SubResource("TileSetAtlasSource_vqhsw") -pattern_0 = SubResource("TileMapPattern_xy0lb") +pattern_0 = SubResource("TileMapPattern_vqhsw") [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_xy0lb"] texture = ExtResource("3_md2b6") @@ -233,6 +233,5 @@ tile_set = SubResource("TileSet_he03c") position = Vector2(0, 440) [node name="InitialPositions" type="TileMapLayer" parent="." unique_id=555896823] -visible = false tile_map_data = PackedByteArray("AAD0//3/AAADAAEAAAD1//z/AAADAAEAAAD1//7/AAADAAEAAAD2//3/AAADAAEAAAD5/wMAAAADAAEAAAD4/wIAAAADAAEAAAD6/wQAAAADAAEAAAD7/wMAAAADAAEAAAD8/wQAAAADAAEAAAD9/wMAAAADAAEAAAD+/wQAAAADAAEAAAD//wMAAAADAAEAAAAAAAMAAAADAAEAAAABAAQAAAADAAEAAAACAAMAAAADAAEAAAADAAQAAAADAAEAAAAEAAMAAAADAAEAAAAFAAQAAAADAAEAAAAGAAMAAAADAAEAAAAHAAIAAAADAAEAAAD8////AAADAAEAAAD9//7/AAADAAEAAAD+//3/AAADAAEAAAD///7/AAADAAEAAAAAAP7/AAADAAEAAAABAP3/AAADAAEAAAACAP7/AAADAAEAAAADAP//AAADAAEAAAAJAP3/AAADAAEAAAAKAP7/AAADAAEAAAALAP3/AAADAAEAAAAKAPz/AAADAAEAAAA=") tile_set = SubResource("TileSet_vqhsw")