work on minimap
This commit is contained in:
parent
3bb0315912
commit
2565028ad0
4 changed files with 33 additions and 21 deletions
|
|
@ -263,6 +263,7 @@ public class MinimapCapture : IFrameConsumer, IDisposable
|
||||||
_colorTracker.SampleFrame(hsv, wallMask);
|
_colorTracker.SampleFrame(hsv, wallMask);
|
||||||
|
|
||||||
using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3));
|
using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3));
|
||||||
|
Cv2.MorphologyEx(wallMask, wallMask, MorphTypes.Close, kernel); // fill 1-2px gaps
|
||||||
Cv2.Dilate(wallMask, wallMask, kernel);
|
Cv2.Dilate(wallMask, wallMask, kernel);
|
||||||
|
|
||||||
FilterSmallComponents(wallMask, _config.WallMinArea);
|
FilterSmallComponents(wallMask, _config.WallMinArea);
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ public class NavigationExecutor : IDisposable
|
||||||
if (gdx * gdx + gdy * gdy < 20 * 20)
|
if (gdx * gdx + gdy * gdy < 20 * 20)
|
||||||
{
|
{
|
||||||
Log.Information("Checkpoint reached at ({X},{Y})", goal.X, goal.Y);
|
Log.Information("Checkpoint reached at ({X},{Y})", goal.X, goal.Y);
|
||||||
|
_worldMap.RemoveCheckpointOff(goal);
|
||||||
_checkpointGoal = null;
|
_checkpointGoal = null;
|
||||||
_currentPath = null; // force re-path
|
_currentPath = null; // force re-path
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,15 +332,14 @@ public class WorldMap : IDisposable
|
||||||
dstRoi.Set(row, col, (byte)MapCell.Explored);
|
dstRoi.Set(row, col, (byte)MapCell.Explored);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark fog on canvas (on top of Unknown or Explored — not Wall)
|
// Mark fog on canvas (only on Unknown cells — never overwrite Explored)
|
||||||
if (isCorner)
|
if (isCorner)
|
||||||
{
|
{
|
||||||
for (var row = 0; row < h; row++)
|
for (var row = 0; row < h; row++)
|
||||||
for (var col = 0; col < w; col++)
|
for (var col = 0; col < w; col++)
|
||||||
{
|
{
|
||||||
if (srcRoi.At<byte>(row, col) != (byte)MapCell.Fog) continue;
|
if (srcRoi.At<byte>(row, col) != (byte)MapCell.Fog) continue;
|
||||||
var dst = dstRoi.At<byte>(row, col);
|
if (dstRoi.At<byte>(row, col) == (byte)MapCell.Unknown)
|
||||||
if (dst == (byte)MapCell.Unknown || dst == (byte)MapCell.Explored)
|
|
||||||
dstRoi.Set(row, col, (byte)MapCell.Fog);
|
dstRoi.Set(row, col, (byte)MapCell.Fog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -359,8 +358,7 @@ public class WorldMap : IDisposable
|
||||||
var fy = srcY + row - halfSize;
|
var fy = srcY + row - halfSize;
|
||||||
if (fx * fx + fy * fy < fogInner2) continue;
|
if (fx * fx + fy * fy < fogInner2) continue;
|
||||||
|
|
||||||
var dst = dstRoi.At<byte>(row, col);
|
if (dstRoi.At<byte>(row, col) == (byte)MapCell.Unknown)
|
||||||
if (dst == (byte)MapCell.Unknown || dst == (byte)MapCell.Explored)
|
|
||||||
dstRoi.Set(row, col, (byte)MapCell.Fog);
|
dstRoi.Set(row, col, (byte)MapCell.Fog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -368,10 +366,7 @@ public class WorldMap : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mark explored area: circle around player position.
|
/// Mark explored area: circle around player position, overwrite Unknown and Fog cells.
|
||||||
/// Unknown cells are marked Explored within the full radius.
|
|
||||||
/// Fog cells are only cleared in the inner portion (fogClearRadius),
|
|
||||||
/// preserving fog at the edge so it stays visible on the viewport.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PaintExploredCircle(MapPosition position)
|
private void PaintExploredCircle(MapPosition position)
|
||||||
{
|
{
|
||||||
|
|
@ -379,8 +374,6 @@ public class WorldMap : IDisposable
|
||||||
var pcy = (int)Math.Round(position.Y);
|
var pcy = (int)Math.Round(position.Y);
|
||||||
var r = _config.ExploredRadius;
|
var r = _config.ExploredRadius;
|
||||||
var r2 = r * r;
|
var r2 = r * r;
|
||||||
var fogClear = r - 20;
|
|
||||||
var fogClear2 = fogClear * fogClear;
|
|
||||||
|
|
||||||
var y0 = Math.Max(0, pcy - r);
|
var y0 = Math.Max(0, pcy - r);
|
||||||
var y1 = Math.Min(_canvasSize - 1, pcy + r);
|
var y1 = Math.Min(_canvasSize - 1, pcy + r);
|
||||||
|
|
@ -392,12 +385,9 @@ public class WorldMap : IDisposable
|
||||||
{
|
{
|
||||||
var dx = x - pcx;
|
var dx = x - pcx;
|
||||||
var dy = y - pcy;
|
var dy = y - pcy;
|
||||||
var d2 = dx * dx + dy * dy;
|
if (dx * dx + dy * dy > r2) continue;
|
||||||
if (d2 > r2) continue;
|
|
||||||
var cell = _canvas.At<byte>(y, x);
|
var cell = _canvas.At<byte>(y, x);
|
||||||
if (cell == (byte)MapCell.Unknown)
|
if (cell == (byte)MapCell.Unknown || cell == (byte)MapCell.Fog)
|
||||||
_canvas.Set(y, x, (byte)MapCell.Explored);
|
|
||||||
else if (cell == (byte)MapCell.Fog && d2 <= fogClear2)
|
|
||||||
_canvas.Set(y, x, (byte)MapCell.Explored);
|
_canvas.Set(y, x, (byte)MapCell.Explored);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -604,6 +594,24 @@ public class WorldMap : IDisposable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a checkpoint from the off list (e.g. when the player has reached it).
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveCheckpointOff(Point cp, int radius = 20)
|
||||||
|
{
|
||||||
|
var r2 = radius * radius;
|
||||||
|
for (var i = _checkpointsOff.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var dx = _checkpointsOff[i].Pos.X - cp.X;
|
||||||
|
var dy = _checkpointsOff[i].Pos.Y - cp.Y;
|
||||||
|
if (dx * dx + dy * dy <= r2)
|
||||||
|
{
|
||||||
|
_checkpointsOff.RemoveAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the nearest unactivated checkpoint within maxDist canvas pixels, or null.
|
/// Returns the nearest unactivated checkpoint within maxDist canvas pixels, or null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,12 @@
|
||||||
<TabItem Header="State">
|
<TabItem Header="State">
|
||||||
<Grid RowDefinitions="Auto,*" Margin="0,6,0,0">
|
<Grid RowDefinitions="Auto,*" Margin="0,6,0,0">
|
||||||
|
|
||||||
<!-- Top row: Inventory + Minimap side by side -->
|
<!-- Top row: Inventory + Minimap side by side (splitter-resizable) -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Margin="0,0,0,6">
|
<Grid Grid.Row="0" ColumnDefinitions="*,5,300" Margin="0,0,0,6">
|
||||||
|
|
||||||
<!-- Inventory Grid (12x5) -->
|
<!-- Inventory Grid (12x5) -->
|
||||||
<Border Grid.Column="0" Background="#161b22" BorderBrush="#30363d"
|
<Border Grid.Column="0" Background="#161b22" BorderBrush="#30363d"
|
||||||
BorderThickness="1" CornerRadius="8" Padding="8" Margin="0,0,6,0">
|
BorderThickness="1" CornerRadius="8" Padding="8" MinWidth="200">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,4">
|
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,0,0,4">
|
||||||
<TextBlock Text="INVENTORY" FontSize="11" FontWeight="SemiBold"
|
<TextBlock Text="INVENTORY" FontSize="11" FontWeight="SemiBold"
|
||||||
|
|
@ -107,9 +107,11 @@
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
<GridSplitter Grid.Column="1" Background="Transparent" />
|
||||||
|
|
||||||
<!-- Minimap -->
|
<!-- Minimap -->
|
||||||
<Border Grid.Column="1" Background="#161b22" BorderBrush="#30363d"
|
<Border Grid.Column="2" Background="#161b22" BorderBrush="#30363d"
|
||||||
BorderThickness="1" CornerRadius="8" Padding="8" Width="300">
|
BorderThickness="1" CornerRadius="8" Padding="8" MinWidth="150">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<Grid DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto" Margin="0,0,0,4">
|
<Grid DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto" Margin="0,0,0,4">
|
||||||
<TextBlock Grid.Column="0" Text="MINIMAP" FontSize="11" FontWeight="SemiBold"
|
<TextBlock Grid.Column="0" Text="MINIMAP" FontSize="11" FontWeight="SemiBold"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue