1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
using Godot;
using System;
using System.Linq;
using System.Net.NetworkInformation;
public partial class DungeonGenerator : Node
{
[ExportCategory("Dimension")]
[Export]
private int width = 80;
[Export]
private int height = 60;
[ExportCategory("RNG")]
private RandomNumberGenerator rng = new();
[Export]
private ulong seed;
[Export]
private bool useSeed = true;
[Export]
private int maxRooms = 10;
[Export]
private int roomMaxWidth = 10;
[Export]
private int roomMinWidth = 3;
[Export]
private int roomMaxHeight = 10;
[Export]
private int roomMinHeight = 2;
public override void _Ready()
{
base._Ready();
if (useSeed) {
rng.Seed = seed;
}
}
private static void CarveTile(MapData data, Vector2I pos)
{
Tile tile = data.GetTile(pos);
if (tile == null) return;
tile.SetDefinition(MapData.floorDefinition);
}
private static void CarveRoom(MapData data, Rect2I room)
{
Rect2I inner = room.Grow(-1);
for (int y = inner.Position.Y; y <= inner.End.Y; y++)
{
for (int x = inner.Position.X; x <= inner.End.X; x++)
{
CarveTile(data, new Vector2I(x, y));
}
}
}
public MapData GenerateDungeon(Player player)
{
MapData data = new MapData(width, height);
Godot.Collections.Array<Rect2I> rooms = [];
for (int tryroom = 0; tryroom < maxRooms; tryroom++) {
int roomWidth = rng.RandiRange(roomMinWidth, roomMaxWidth);
int roomHeight = rng.RandiRange(roomMinHeight, roomMaxHeight);
int x = rng.RandiRange(0, data.Width - 1 - roomWidth);
int y = rng.RandiRange(0, data.Height - 1 - roomHeight);
Rect2I newRoom = new(x, y, roomWidth, roomHeight);
bool intersects = false;
foreach (Rect2I room in rooms) {
if (newRoom.Intersects(room)) {
intersects = true;
break;
}
}
if (intersects) {
continue;
}
CarveRoom(data, newRoom);
if (rooms.Count <= 0) {
player.GridPosition = newRoom.GetCenter();
} else {
TunnelBetween(data, rooms.Last().GetCenter(), newRoom.GetCenter());
}
rooms.Add(newRoom);
}
return data;
}
private static void HorizontalCorridor(MapData data, int y, int xBegin, int xEnd) {
int begin = (xBegin < xEnd) ? xBegin : xEnd;
int end = (xEnd > xBegin) ? xEnd : xBegin;
for (int i = begin; i <= end; i++) {
CarveTile(data, new Vector2I(i, y));
}
}
private static void VerticalCorridor(MapData data, int x, int yBegin, int yEnd) {
int begin = (yBegin < yEnd) ? yBegin : yEnd;
int end = (yEnd > yBegin) ? yEnd : yBegin;
for (int i = begin; i <= end; i++) {
CarveTile(data, new Vector2I(x, i));
}
}
private void TunnelBetween(MapData data, Vector2I start, Vector2I end) {
HorizontalCorridor(data, start.Y, start.X, end.X);
VerticalCorridor(data, end.X, start.Y, end.Y);
}
}
|