Finished robot display, fixed test run for For-Node

This commit is contained in:
2026-05-14 21:01:56 +02:00
parent 6084761e0d
commit eee59b6385
3 changed files with 219 additions and 28 deletions
+3 -3
View File
@@ -474,9 +474,9 @@ public partial class TestRunner : Node
amount = 2 amount = 2
}; };
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "first iteration"); AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "first iteration");
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "second iteration"); AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "second iteration");
AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "loop finished"); AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "loop finished");
} }
private void TestStartNodeSucceedsImmediately() private void TestStartNodeSucceedsImmediately()
+5
View File
@@ -154,4 +154,9 @@ public static class UIStyle
{ {
return Warning; return Warning;
} }
public static Color GetBorderColor()
{
return Accent;
}
} }
+211 -25
View File
@@ -4,38 +4,43 @@ using System.Collections.Generic;
public partial class Map : PanelContainer public partial class Map : PanelContainer
{ {
private const int TileTextureSize = 32;
private const int RobotBorderWidth = 2;
private const double RobotMapUpdateInterval = 0.2;
[Export] GridContainer grid; [Export] GridContainer grid;
private HashSet<Tile> handledTiles = new HashSet<Tile>(); private HashSet<Tile> handledTiles = new HashSet<Tile>();
private Dictionary<Tile, TextureRect> textureMap = new Dictionary<Tile, TextureRect>(); private Dictionary<Tile, TextureRect> textureMap = new Dictionary<Tile, TextureRect>();
private Dictionary<Vector2I, List<Robot>> visibleRobots = new Dictionary<Vector2I, List<Robot>>();
private double robotMapUpdateTimer = 0.0;
public override void _Ready() public override void _Ready()
{ {
grid.Columns = GameData.layerSize + 1; grid.Columns = GameData.layerSize + 1;
} }
public override void _Process(double delta)
{
if (!Visible) return;
robotMapUpdateTimer += delta;
if (robotMapUpdateTimer < RobotMapUpdateInterval) return;
robotMapUpdateTimer = 0.0;
UpdateVisibleRobotTiles();
}
public void ShowMap() public void ShowMap()
{ {
if (!Visible) return; if (!Visible) return;
ClearGrid(); ClearGrid();
robotMapUpdateTimer = 0.0;
Tile[,] tiles = GameData.map[GameData.currentLayer].tiles; Tile[,] tiles = GameData.map[GameData.currentLayer].tiles;
int size = GameData.layerSize; int size = GameData.layerSize;
Dictionary<Vector2I, List<Robot>> visibleRobots = new Dictionary<Vector2I, List<Robot>>(); visibleRobots = BuildVisibleRobots();
Vector3I tilePos;
Vector2I key;
foreach(Robot robot in GameData.robots)
{
if(!robot.showOnMap) continue;
tilePos = Pathfinding.GetClosestStartPoint(robot.Position);
if(tilePos.Y != GameData.visibleLayer) continue;
key = new Vector2I(tilePos.X, tilePos.Z);
if(!visibleRobots.ContainsKey(key)) visibleRobots.Add(key, new List<Robot>());
visibleRobots[key].Add(robot);
}
for (int z = -1; z < size; z++) for (int z = -1; z < size; z++)
{ {
@@ -47,7 +52,8 @@ public partial class Map : PanelContainer
continue; continue;
} }
TextureRect texture = CreateTileTexture(tiles[x, z]); Vector2I tilePosition = new Vector2I(x, z);
TextureRect texture = CreateTileTexture(tiles[x, z], GetRobotsOnTile(visibleRobots, tilePosition));
textureMap[tiles[x, z]] = texture; textureMap[tiles[x, z]] = texture;
if (!handledTiles.Contains(tiles[x, z])) if (!handledTiles.Contains(tiles[x, z]))
@@ -65,6 +71,116 @@ public partial class Map : PanelContainer
} }
} }
private void UpdateVisibleRobotTiles()
{
Dictionary<Vector2I, List<Robot>> updatedVisibleRobots = BuildVisibleRobots();
if (HasSameVisibleRobots(visibleRobots, updatedVisibleRobots)) return;
List<Vector2I> affectedTiles = GetAffectedRobotTiles(visibleRobots, updatedVisibleRobots);
visibleRobots = updatedVisibleRobots;
foreach (Vector2I tilePosition in affectedTiles)
{
UpdateTileAtPosition(tilePosition);
}
}
private bool HasSameVisibleRobots(
Dictionary<Vector2I, List<Robot>> oldRobots,
Dictionary<Vector2I, List<Robot>> newRobots
)
{
if (oldRobots.Count != newRobots.Count) return false;
foreach (KeyValuePair<Vector2I, List<Robot>> kvp in oldRobots)
{
if (!newRobots.ContainsKey(kvp.Key)) return false;
if (!ContainsSameRobots(kvp.Value, newRobots[kvp.Key])) return false;
}
return true;
}
private bool ContainsSameRobots(List<Robot> oldRobots, List<Robot> newRobots)
{
if (oldRobots.Count != newRobots.Count) return false;
foreach (Robot robot in oldRobots)
{
if (!newRobots.Contains(robot)) return false;
}
return true;
}
private List<Vector2I> GetAffectedRobotTiles(
Dictionary<Vector2I, List<Robot>> oldRobots,
Dictionary<Vector2I, List<Robot>> newRobots
)
{
List<Vector2I> affectedTiles = new List<Vector2I>();
foreach (Vector2I tilePosition in oldRobots.Keys)
{
AddAffectedTile(affectedTiles, tilePosition);
}
foreach (Vector2I tilePosition in newRobots.Keys)
{
AddAffectedTile(affectedTiles, tilePosition);
}
return affectedTiles;
}
private void AddAffectedTile(List<Vector2I> affectedTiles, Vector2I tilePosition)
{
if (affectedTiles.Contains(tilePosition)) return;
affectedTiles.Add(tilePosition);
}
private void UpdateTileAtPosition(Vector2I tilePosition)
{
if (tilePosition.X < 0 || tilePosition.X >= GameData.layerSize) return;
if (tilePosition.Y < 0 || tilePosition.Y >= GameData.layerSize) return;
Tile tile = GameData.map[GameData.currentLayer].tiles[tilePosition.X, tilePosition.Y];
if (!textureMap.ContainsKey(tile)) return;
UpdateMap(tile, textureMap[tile]);
}
private Dictionary<Vector2I, List<Robot>> BuildVisibleRobots()
{
Dictionary<Vector2I, List<Robot>> visibleRobots = new Dictionary<Vector2I, List<Robot>>();
foreach (Robot robot in GameData.robots)
{
if (!robot.showOnMap) continue;
Vector3I tilePos = Pathfinding.GetClosestStartPoint(robot.Position);
if (tilePos.Y != GameData.currentLayer) continue;
Vector2I key = new Vector2I(tilePos.X, tilePos.Z);
if (!visibleRobots.ContainsKey(key))
{
visibleRobots.Add(key, new List<Robot>());
}
visibleRobots[key].Add(robot);
}
return visibleRobots;
}
private List<Robot> GetRobotsOnTile(Dictionary<Vector2I, List<Robot>> visibleRobots, Vector2I tilePosition)
{
if (!visibleRobots.ContainsKey(tilePosition)) return new List<Robot>();
return visibleRobots[tilePosition];
}
private void ClearGrid() private void ClearGrid()
{ {
foreach (Node node in grid.GetChildren()) foreach (Node node in grid.GetChildren())
@@ -91,7 +207,7 @@ public partial class Map : PanelContainer
return label; return label;
} }
private TextureRect CreateTileTexture(Tile tile) private TextureRect CreateTileTexture(Tile tile, List<Robot> robotsOnTile)
{ {
TextureRect texture = new TextureRect TextureRect texture = new TextureRect
{ {
@@ -100,7 +216,7 @@ public partial class Map : PanelContainer
StretchMode = TextureRect.StretchModeEnum.Scale StretchMode = TextureRect.StretchModeEnum.Scale
}; };
UpdateTileTexture(tile, texture); UpdateTileTexture(tile, texture, robotsOnTile);
return texture; return texture;
} }
@@ -121,26 +237,41 @@ public partial class Map : PanelContainer
{ {
if (!IsInstanceValid(texture)) return; if (!IsInstanceValid(texture)) return;
UpdateTileTexture(tile, texture); UpdateTileTexture(tile, texture, GetRobotsOnTile(
BuildVisibleRobots(),
tile.GridPosition
));
} }
private void UpdateTileTexture(Tile tile, TextureRect texture) private void UpdateTileTexture(Tile tile, TextureRect texture, List<Robot> robotsOnTile)
{ {
Texture2D tileTexture;
string tooltipText;
if (!tile.wasVisited && !GameData.debugMode) if (!tile.wasVisited && !GameData.debugMode)
{ {
texture.Texture = GenerateTexture(32, new Color(0, 0, 0, 1)); tileTexture = GenerateTexture(TileTextureSize, new Color(0, 0, 0, 1));
texture.TooltipText = "Not explored"; tooltipText = "Not explored";
} }
else if (tile.containsResource) else if (tile.containsResource)
{ {
texture.Texture = ResourceDistributor.resources[tile.resource.name]; tileTexture = ResourceDistributor.resources[tile.resource.name];
texture.TooltipText = tile.resource.item.GetReadableName() + $"\r(X: {tile.GridPosition.X},Y: {GameData.currentLayer},Z: {tile.GridPosition.Y})"; tooltipText = tile.resource.item.GetReadableName() + GetPositionTooltip(tile);
} }
else else
{ {
texture.Texture = GenerateTexture(32, new Color(0, 0, 0, 0)); tileTexture = GenerateTexture(TileTextureSize, new Color(0, 0, 0, 0));
texture.TooltipText = ""; tooltipText = "";
} }
if (robotsOnTile.Count > 0)
{
tileTexture = AddBorder(tileTexture, UIStyle.GetBorderColor(), RobotBorderWidth);
tooltipText += GetRobotTooltip(robotsOnTile, tooltipText.Length > 0);
}
texture.Texture = tileTexture;
texture.TooltipText = tooltipText;
} }
public Texture2D GenerateTexture(int size, Color fillColor) public Texture2D GenerateTexture(int size, Color fillColor)
@@ -150,4 +281,59 @@ public partial class Map : PanelContainer
return ImageTexture.CreateFromImage(image); return ImageTexture.CreateFromImage(image);
} }
public Texture2D AddBorder(Texture2D texture, Color borderColor, int borderWidth)
{
if (texture == null) return null;
if (borderWidth <= 0) return texture;
Image sourceImage = texture.GetImage();
if (sourceImage == null) return texture;
if (sourceImage.GetFormat() != Image.Format.Rgba8)
{
sourceImage.Convert(Image.Format.Rgba8);
}
int width = sourceImage.GetWidth();
int height = sourceImage.GetHeight();
int actualBorderWidth = Math.Min(borderWidth, Math.Min(width, height) / 2);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < actualBorderWidth; y++)
{
sourceImage.SetPixel(x, y, borderColor);
sourceImage.SetPixel(x, height - 1 - y, borderColor);
}
}
for (int y = actualBorderWidth; y < height - actualBorderWidth; y++)
{
for (int x = 0; x < actualBorderWidth; x++)
{
sourceImage.SetPixel(x, y, borderColor);
sourceImage.SetPixel(width - 1 - x, y, borderColor);
}
}
return ImageTexture.CreateFromImage(sourceImage);
}
private string GetPositionTooltip(Tile tile)
{
return $"\r(X: {tile.GridPosition.X},Y: {GameData.currentLayer},Z: {tile.GridPosition.Y})";
}
private string GetRobotTooltip(List<Robot> robotsOnTile, bool addSeparator)
{
string tooltip = addSeparator ? "\rRobots:" : "Robots:";
foreach (Robot robot in robotsOnTile)
{
tooltip += "\r- " + robot.Name;
}
return tooltip;
}
} }