Automatic doors

This commit is contained in:
Marco 2025-04-23 13:38:54 +02:00
commit 3fc39f63c4
29 changed files with 401 additions and 525 deletions

View file

@ -10,6 +10,7 @@ using Godot.Collections;
namespace Cirno.Scripts.Controllers;
[Tool]
public partial class RogueliteRoom : Node2D
{
[Export] public RogueliteRoomResource RoomResource { get; set; }
@ -18,6 +19,8 @@ public partial class RogueliteRoom : Node2D
public Vector2I BottomLeft => GridPosition + new Vector2I(0, RoomResource.Size.Y - 1);
private Vector2 BaseRoomSize => new Vector2(320, 160);
public Vector2I RandomBottomExit()
{
return BottomLeft + new Vector2I(GD.RandRange(0, RoomResource.Size.X - 1), 0);
@ -37,6 +40,8 @@ public partial class RogueliteRoom : Node2D
}
[Export] public PackedScene DoorPrefab { get; private set; }
[Export] public PackedScene VerticalDoorPrefab { get; private set; }
[Export] public PackedScene WallPrefab { get; private set; }
private static readonly Godot.Collections.Dictionary<string, Vector2I> DirectionMap = new()
@ -76,24 +81,68 @@ public partial class RogueliteRoom : Node2D
}
}
private List<DoorMarker> GenerateDoors()
{
List<DoorMarker> doors = [];
var doorsContainer = new Node2D();
this.AddChild(doorsContainer);
doorsContainer.Name = "Doors";
// North
for (int i = 0; i < RoomResource.Size.X; i++)
{
if (RoomResource.HasDoors(DoorDirections.North))
{
doors.Add(MakeDoorMarker(DoorDirections.North, i));
}
if (RoomResource.HasDoors(DoorDirections.South))
{
doors.Add(MakeDoorMarker(DoorDirections.South, i));
}
}
for (int j = 0; j < RoomResource.Size.Y; j++)
{
doors.Add(MakeDoorMarker(DoorDirections.East, j));
doors.Add(MakeDoorMarker(DoorDirections.West, j));
}
foreach (var door in doors)
{
doorsContainer.AddChild(door);
}
return doors;
}
private DoorMarker MakeDoorMarker(DoorDirections direction, int wallIndex)
{
var doorMarker = new DoorMarker();
doorMarker.Direction = direction;
doorMarker.WallIndex = wallIndex;
doorMarker.Position = GetDoorPosition(direction, wallIndex);
return doorMarker;
}
public void HandleDoors(Func<Vector2I, Vector2I, RoomConnection> connectionChecker)
{
if (!HasNode("Doors")) return;
var doorsNode = GetNode("Doors");
foreach (Node child in doorsNode.GetChildren())
var doors = GenerateDoors();
foreach (DoorMarker marker in doors)
{
if (child is not DoorMarker marker) continue;
var baseDir = marker.GetWorldDirection();
// WallIndex determines the offset *along* the edge of the room
Vector2I offset = marker.Direction switch
{
RoomDirection.North => new Vector2I(marker.WallIndex, 0),
RoomDirection.South => new Vector2I(marker.WallIndex, RoomResource.Size.Y - 1),
RoomDirection.East => new Vector2I(RoomResource.Size.X - 1, marker.WallIndex),
RoomDirection.West => new Vector2I(0, marker.WallIndex),
DoorDirections.North => new Vector2I(marker.WallIndex, 0),
DoorDirections.South => new Vector2I(marker.WallIndex, RoomResource.Size.Y - 1),
DoorDirections.East => new Vector2I(RoomResource.Size.X - 1, marker.WallIndex),
DoorDirections.West => new Vector2I(0, marker.WallIndex),
_ => Vector2I.Zero
};
@ -107,7 +156,14 @@ public partial class RogueliteRoom : Node2D
if (connected)
{
var door = this.CreateChildOf<Door>(marker, DoorPrefab, marker.GlobalPosition);
var door = this.CreateChildOf<Door>(marker, marker.Direction switch
{
DoorDirections.North => DoorPrefab,
DoorDirections.South => DoorPrefab,
DoorDirections.East => VerticalDoorPrefab,
DoorDirections.West => VerticalDoorPrefab,
_ => throw new ArgumentOutOfRangeException()
}, marker.GlobalPosition);
door.State = DoorState.Closed;
@ -234,4 +290,53 @@ public partial class RogueliteRoom : Node2D
{
return $"{GridPosition} {RoomResource}";
}
public Vector2 GetDoorPosition(DoorDirections direction, int wallIndex)
{
return direction switch
{
DoorDirections.North => new Vector2((BaseRoomSize.X / 2) + (BaseRoomSize.X * wallIndex), 32),
DoorDirections.South => new Vector2((BaseRoomSize.X / 2) + (BaseRoomSize.X * wallIndex),
((BaseRoomSize.Y) * RoomResource.Size.Y) +2 ),
DoorDirections.East => new Vector2((BaseRoomSize.X * RoomResource.Size.X) - 12, (BaseRoomSize.Y / 2) + (BaseRoomSize.Y * wallIndex) - 8),
DoorDirections.West => new Vector2(12, (BaseRoomSize.Y / 2) + (BaseRoomSize.Y * wallIndex) - 8),
_ => Vector2.Zero
};
}
// [ExportToolButton("Arrange Doors")] public Callable ArrangeDoorsButton => Callable.From(ArrangeDoors);
public void ArrangeDoors()
{
var doorNode = this.GetNode("Doors");
var doors = doorNode.GetChildren();
foreach (var node in doors)
{
if (node is DoorMarker doorMarker)
{
GD.Print($"{doorMarker.Name} {doorMarker.Direction} {doorMarker.WallIndex}");
var baseGridSize = new Vector2(320, 160);
Vector2 doorPosition = doorMarker.Direction switch
{
DoorDirections.North => new Vector2((baseGridSize.X / 2) + (baseGridSize.X * doorMarker.WallIndex), 32),
DoorDirections.South => new Vector2((baseGridSize.X / 2) + (baseGridSize.X * doorMarker.WallIndex),
((baseGridSize.Y) * RoomResource.Size.Y) +2 ),
DoorDirections.East => doorMarker.Position,
DoorDirections.West => doorMarker.Position,
_ => doorMarker.Position
};
doorMarker.Position = doorPosition;
}
else
{
GD.Print($"Node was something else: {node}");
}
}
}
}