Restore dual terrain tilemap rendering

This commit is contained in:
2026-05-10 23:04:48 +02:00
parent 3a52db0071
commit 1b9372ff7c

View File

@@ -24,6 +24,11 @@ public sealed partial class MainWindow
{ {
return new(OriginX + (position.X * CellSize), OriginY + (position.Y * CellSize), CellSize, CellSize); return new(OriginX + (position.X * CellSize), OriginY + (position.Y * CellSize), CellSize, CellSize);
} }
public Rect DualTileRect(int x, int y)
{
return new(OriginX + ((x - 0.5) * CellSize), OriginY + ((y - 0.5) * CellSize), CellSize, CellSize);
}
} }
private sealed record ForecastViewModel(string Message); private sealed record ForecastViewModel(string Message);
@@ -301,14 +306,84 @@ public sealed partial class MainWindow
private void DrawTerrain(CanvasDrawingSession drawing, CanvasLayout layout) private void DrawTerrain(CanvasDrawingSession drawing, CanvasLayout layout)
{ {
foreach (var position in AllPositions()) for (var y = 0; y <= m_Level.Height; y++)
{ {
var rect = layout.CellRect(position); for (var x = 0; x <= m_Level.Width; x++)
var color = m_Level.GetTerrain(position) == ECellTerrain.Wall ? ColorHelper.FromArgb(255, 41, 47, 52) : ColorHelper.FromArgb(255, 32, 38, 42); DrawDualTerrainTile(drawing, layout.DualTileRect(x, y), GetDualTileMask(x, y));
drawing.FillRectangle(rect, color);
} }
} }
private void DrawDualTerrainTile(CanvasDrawingSession drawing, Rect rect, int floorMask)
{
if (m_TerrainTilemap is null)
{
DrawFallbackTerrainTile(drawing, rect, floorMask);
return;
}
var wallMask = c_AllCorners ^ floorMask;
drawing.DrawImage(m_TerrainTilemap, rect, TilemapSourceRect(wallMask), 1.0f, CanvasImageInterpolation.HighQualityCubic);
}
private static void DrawFallbackTerrainTile(CanvasDrawingSession drawing, Rect rect, int floorMask)
{
var color = floorMask == c_AllCorners ? ColorHelper.FromArgb(255, 32, 38, 42) : ColorHelper.FromArgb(255, 41, 47, 52);
drawing.FillRectangle(rect, color);
}
private static Rect TilemapSourceRect(int wallMask)
{
var tilePosition = wallMask switch {
c_BottomLeftCorner => new GridPosition(0, 0),
c_TopRightCorner | c_BottomRightCorner => new(1, 0),
c_TopLeftCorner | c_BottomLeftCorner | c_BottomRightCorner => new(2, 0),
c_BottomLeftCorner | c_BottomRightCorner => new(3, 0),
c_TopLeftCorner | c_BottomRightCorner => new(0, 1),
c_BottomLeftCorner | c_TopRightCorner | c_BottomRightCorner => new(1, 1),
c_AllCorners => new(2, 1),
c_TopLeftCorner | c_BottomLeftCorner | c_TopRightCorner => new(3, 1),
c_TopRightCorner => new(0, 2),
c_TopLeftCorner | c_TopRightCorner => new(1, 2),
c_TopLeftCorner | c_TopRightCorner | c_BottomRightCorner => new(2, 2),
c_BottomLeftCorner | c_TopLeftCorner => new(3, 2),
0 => new(0, 3),
c_BottomRightCorner => new(1, 3),
c_BottomLeftCorner | c_TopRightCorner => new(2, 3),
c_TopLeftCorner => new GridPosition(3, 3),
_ => throw new ArgumentOutOfRangeException(nameof(wallMask), wallMask, "Unsupported tile mask.")
};
return new(
tilePosition.X * c_TilemapTileSize,
tilePosition.Y * c_TilemapTileSize,
c_TilemapTileSize,
c_TilemapTileSize);
}
private int GetDualTileMask(int x, int y)
{
var mask = 0;
if (GetTerrainOrWall(x - 1, y - 1) == ECellTerrain.Floor)
mask |= c_TopLeftCorner;
if (GetTerrainOrWall(x, y - 1) == ECellTerrain.Floor)
mask |= c_TopRightCorner;
if (GetTerrainOrWall(x - 1, y) == ECellTerrain.Floor)
mask |= c_BottomLeftCorner;
if (GetTerrainOrWall(x, y) == ECellTerrain.Floor)
mask |= c_BottomRightCorner;
return mask;
}
private ECellTerrain GetTerrainOrWall(int x, int y)
{
var position = new GridPosition(x, y);
return m_Level.InBounds(position) ? m_Level.GetTerrain(position) : ECellTerrain.Wall;
}
private void DrawUnderground(CanvasDrawingSession drawing, CanvasLayout layout) private void DrawUnderground(CanvasDrawingSession drawing, CanvasLayout layout)
{ {
foreach (var position in AllPositions()) foreach (var position in AllPositions())
@@ -908,6 +983,12 @@ public sealed partial class MainWindow
private const double c_MaxZoom = 4; private const double c_MaxZoom = 4;
private const double c_ZoomStep = 1.15; private const double c_ZoomStep = 1.15;
private const double c_ClickPixelThreshold = 10; private const double c_ClickPixelThreshold = 10;
private const int c_TilemapTileSize = 512;
private const int c_TopLeftCorner = 1;
private const int c_TopRightCorner = 2;
private const int c_BottomLeftCorner = 4;
private const int c_BottomRightCorner = 8;
private const int c_AllCorners = c_TopLeftCorner | c_TopRightCorner | c_BottomLeftCorner | c_BottomRightCorner;
private static readonly Color c_FuelColor = ColorHelper.FromArgb(255, 220, 170, 68); private static readonly Color c_FuelColor = ColorHelper.FromArgb(255, 220, 170, 68);
private static readonly Color c_CoolantColor = ColorHelper.FromArgb(255, 57, 174, 196); private static readonly Color c_CoolantColor = ColorHelper.FromArgb(255, 57, 174, 196);
private static readonly Color c_ElectricityColor = ColorHelper.FromArgb(255, 236, 226, 82); private static readonly Color c_ElectricityColor = ColorHelper.FromArgb(255, 236, 226, 82);