Cleaned up project with better structure.

This commit is contained in:
2026-05-09 11:29:48 +02:00
parent 1ad3454f6a
commit 6708aa277f
95 changed files with 711 additions and 700 deletions
+278
View File
@@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
public class WFC
{
public static Dictionary<string, Dictionary<Direction, List<string>>> adjacency = new Dictionary<string, Dictionary<Direction, List<string>>>();
public enum Direction
{
Backward,
Forward,
Left,
Right,
None,
Up,
Down
}
public static readonly Direction[] dirs =
{
Direction.Backward,
Direction.Forward,
Direction.Left,
Direction.Right,
Direction.Up,
Direction.Down
};
public static readonly Vector2I[] offsets2D =
{
new Vector2I(0, -1),
new Vector2I(0, 1),
new Vector2I(-1, 0),
new Vector2I(1, 0)
};
public static readonly Vector3I[] offsets3D =
{
new Vector3I(0, 0, -1),
new Vector3I(0, 0, 1),
new Vector3I(-1, 0, 0),
new Vector3I(1, 0, 0),
new Vector3I(0, -1, 0),
new Vector3I(0, 1, 0)
};
public static Dictionary<string, HashSet<Direction>> tileConnections = new Dictionary<string, HashSet<Direction>>
{
["t_right"] = new HashSet<Direction> { Direction.Backward, Direction.Forward, Direction.Right, Direction.Up },
["t_left"] = new HashSet<Direction> { Direction.Backward, Direction.Forward, Direction.Left, Direction.Up },
["t_up"] = new HashSet<Direction> { Direction.Left, Direction.Right, Direction.Backward, Direction.Up },
["t_down"] = new HashSet<Direction> { Direction.Left, Direction.Right, Direction.Forward, Direction.Up },
["end_up"] = new HashSet<Direction> { Direction.Backward, Direction.Up },
["end_down"] = new HashSet<Direction> { Direction.Forward, Direction.Up },
["end_left"] = new HashSet<Direction> { Direction.Left, Direction.Up },
["end_right"] = new HashSet<Direction> { Direction.Right, Direction.Up },
["straight_left_right"] = new HashSet<Direction> { Direction.Left, Direction.Right, Direction.Up },
["straight_up_down"] = new HashSet<Direction> { Direction.Backward, Direction.Forward, Direction.Up },
["corner_up_left"] = new HashSet<Direction> { Direction.Backward, Direction.Left, Direction.Up },
["corner_up_right"] = new HashSet<Direction> { Direction.Backward, Direction.Right, Direction.Up },
["corner_down_left"] = new HashSet<Direction> { Direction.Forward, Direction.Left, Direction.Up },
["corner_down_right"] = new HashSet<Direction> { Direction.Forward, Direction.Right, Direction.Up },
["junction"] = new HashSet<Direction> { Direction.Backward, Direction.Forward, Direction.Left, Direction.Right, Direction.Up },
["gate"] = new HashSet<Direction> { Direction.Backward, Direction.Forward, Direction.Left, Direction.Right, Direction.Up, Direction.Down },
["spawn"] = new HashSet<Direction> { Direction.Forward, Direction.Left },
};
public static Dictionary<string, float> weights = new Dictionary<string, float>()
{
["junction"] = 3f,
["t_up"] = 3f,
["t_down"] = 3f,
["t_left"] = 3f,
["t_right"] = 3f,
["straight_left_right"] = 2f,
["straight_up_down"] = 2f,
["corner_up_left"] = 0.7f,
["corner_up_right"] = 0.7f,
["corner_down_left"] = 0.7f,
["corner_down_right"] = 0.7f,
["end_up"] = 0.2f,
["end_down"] = 0.1f,
["end_left"] = 0.2f,
["end_right"] = 0.3f,
["gate"] = 0.0f,
["spawn"] = 0.0f
};
public static Direction Opposite(Direction dir)
{
return dir switch
{
Direction.Backward => Direction.Forward,
Direction.Forward => Direction.Backward,
Direction.Left => Direction.Right,
Direction.Right => Direction.Left,
Direction.Up => Direction.Down,
Direction.Down => Direction.Up,
_ => dir
};
}
public static bool CanConnect(string a, string b, Direction direction, bool checkWalking)
{
HashSet<Direction> aDirs = tileConnections[a];
HashSet<Direction> bDirs = tileConnections[b];
bool aOpen = aDirs.Contains(direction);
bool bOpen = bDirs.Contains(Opposite(direction));
if (checkWalking) return aOpen && bOpen;
return aOpen == bOpen;
}
public static void FillAdjacencies()
{
foreach (string tile in tileConnections.Keys)
{
adjacency[tile] = new Dictionary<Direction, List<string>>();
foreach (Direction dir in Enum.GetValues(typeof(Direction)))
{
List<string> valid = new List<string>();
foreach (string other in tileConnections.Keys)
{
if (CanConnect(tile, other, dir, false))
valid.Add(other);
}
adjacency[tile][dir] = valid;
}
}
}
public static bool IsWalkable(Tile tile)
{
HashSet<Direction> connections = tileConnections[tile.collapsedMesh];
return connections.Count > 0 && !connections.Contains(Direction.None);
}
public static bool CanWalk(Tile[,] layer, Vector2I from, Vector2I to, Direction dir)
{
Tile fromTile = layer[from.X, from.Y];
Tile toTile = layer[to.X, to.Y];
if (!IsWalkable(toTile))
return false;
return CanConnect(fromTile.collapsedMesh, toTile.collapsedMesh, dir, true);
}
public static bool CanWalk3D(Vector3I from, Vector3I to)
{
Tile fromTile = GameData.map[from.Y].tiles[from.X, from.Z];
Tile toTile = GameData.map[to.Y].tiles[to.X, to.Z];
if (fromTile == null || toTile == null)
return false;
if (from.Y != to.Y)
{
if (Math.Abs(from.Y - to.Y) != 1)
return false;
if (from.Y > to.Y)
{
return toTile.collapsedMesh == "gate";
}
else
{
return fromTile.collapsedMesh == "gate";
}
}
int dx = to.X - from.X;
int dz = to.Z - from.Z;
if (Math.Abs(dx) + Math.Abs(dz) != 1)
return false;
Direction dir;
if (dx == 1) dir = Direction.Right;
else if (dx == -1) dir = Direction.Left;
else if (dz == 1) dir = Direction.Forward;
else if (dz == -1) dir = Direction.Backward;
else return false;
return CanWalk(
GameData.map[from.Y].tiles,
new Vector2I(from.X, from.Z),
new Vector2I(to.X, to.Z),
dir
);
}
public static bool IsMapConnected(Tile[,] layer, float accessibilityThreshhold)
{
bool result = false;
HashSet<Vector2I> visited = new HashSet<Vector2I>();
List<Vector2I> toCheck = new List<Vector2I>();
Vector2I position;
toCheck.Add(new Vector2I(1, 1));
int safetyCounter = 0;
while (true)
{
if (toCheck.Count <= 0) break;
int index = GameData.rand.Next(toCheck.Count);
position = toCheck[index];
toCheck[index] = toCheck[^1];
toCheck.RemoveAt(toCheck.Count - 1);
if (!visited.Add(position)) continue;
for (int i = 0; i < offsets2D.Length; i++)
{
Vector2I next = position + offsets2D[i];
if (!InBounds(next, layer.GetLength(0)))
continue;
if (CanWalk(layer, position, next, dirs[i]))
{
toCheck.Add(next);
}
}
safetyCounter++;
if (safetyCounter > layer.Length * 2) break;
if (visited.Count >= Math.Pow(layer.GetLength(0) - 1, 2) * accessibilityThreshhold)
{
result = true;
break;
}
}
return result;
}
public static bool InBounds(Vector2I pos, int layerSize)
{
return pos.X > 0 &&
pos.Y > 0 &&
pos.X < layerSize &&
pos.Y < layerSize;
}
public static List<string> GetBorderPossibilities(int x, int z)
{
bool left = x == 0;
bool right = x == GameData.layerSize - 1;
bool top = z == 0;
bool bottom = z == GameData.layerSize - 1;
if (left && top) return new List<string> { "corner_down_right" };
if (left && bottom) return new List<string> { "corner_up_right" };
if (right && top) return new List<string> { "corner_down_left" };
if (right && bottom) return new List<string> { "corner_up_left" };
if (top) return new List<string> { "straight_left_right", "t_down" };
if (bottom) return new List<string> { "straight_left_right", "t_up" };
if (left) return new List<string> { "straight_up_down", "t_right" };
if (right) return new List<string> { "straight_up_down", "t_left" };
return new List<string>();
}
}