Automatic tile avoidance

This commit is contained in:
Marco 2025-03-25 13:51:35 +01:00
commit a861c331da
6 changed files with 94 additions and 20 deletions

View file

@ -45,6 +45,9 @@ public partial class GameManager : Node2D
[Export]
public StringName PauseActionName { get; private set; } = "pause";
[Export]
public TilemapAvoidance NavigationTilemap { get; private set; }
private Node2D _bulletsContainer;
public Node2D BulletsContainer => _bulletsContainer;
@ -354,6 +357,16 @@ public partial class GameManager : Node2D
node.QueueFree();
}
}
public void RecalculateTilemap(Vector2 position)
{
CallDeferred(MethodName.RecalculateTilemapDeferred, position);
}
private void RecalculateTilemapDeferred(Vector2 position)
{
NavigationTilemap.Recalculate(position);
}
}
public enum GameState

View file

@ -1,6 +1,18 @@
using Godot;
using System;
using System.Threading.Tasks;
public partial class NavigationMap : NavigationRegion2D
{
public override void _Ready()
{
_ = RecalculateNavigation();
}
private async Task RecalculateNavigation()
{
await Task.Delay(300);
this.BakeNavigationPolygon();
}
}

View file

@ -1,25 +1,67 @@
using Godot;
using System;
using System.Linq;
using System.Threading.Tasks;
using Godot.Collections;
public partial class TilemapAvoidance : TileMapLayer
{
[Export] private Array<TileMapLayer> _solidLayers;
[Export(PropertyHint.Layers2DPhysics)] public uint ObstaclesCollisionMask { get; private set; }
[Export] private Array<TileMapLayer> _solidLayers;
public override bool _UseTileDataRuntimeUpdate(Vector2I coords)
{
// if (_solidLayer.GetUsedCellsById(0).Contains(coords))
// {
// return true;
// }
private bool _needsFullCheck = false;
return _solidLayers.Aggregate(false, (current, layer) => current | layer.GetUsedCellsById(0).Contains(coords));
}
public override void _Ready()
{
_ = RefreshNavigationAsync();
}
public override void _TileDataRuntimeUpdate(Vector2I coords, TileData tileData)
{
tileData.SetNavigationPolygon(0, null);
}
}
private async Task RefreshNavigationAsync()
{
await Task.Delay(500);
_needsFullCheck = true;
this.NotifyRuntimeTileDataUpdate();
}
public void Recalculate(Vector2 position)
{
var mapPos = LocalToMap(this.ToLocal(position));
var tile = GetCellTileData(mapPos);
tile.SetNavigationPolygon(0, null);
//_UpdateCells([mapPos], false);
}
public override bool _UseTileDataRuntimeUpdate(Vector2I coords)
{
// Run this check and return true only if I know the tiles will need to be updated, which means at start.
//
if (_needsFullCheck)
{
var spaceState = GetWorld2D().DirectSpaceState;
var globalCoords = ToGlobal(this.MapToLocal(coords));
var query = new PhysicsPointQueryParameters2D();
query.Position = globalCoords;
query.CollisionMask = ObstaclesCollisionMask;
query.CollideWithBodies = true;
query.CollideWithAreas = true;
var result = spaceState.IntersectPoint(query);
if (result.Count > 0) return true;
//_needsFullCheck = false;
return _solidLayers.Aggregate(false,
(current, layer) => current | layer.GetUsedCellsById(0).Contains(coords));
}
else
{
return false;
}
}
public override void _TileDataRuntimeUpdate(Vector2I coords, TileData tileData)
{
tileData.SetNavigationPolygon(0, null);
}
}