我正在用C#开发一个程序性的房间生成器,我希望房间不要重叠,并且我很难使它工作。 @Idle_Mind发表评论后,我遇到了一个新问题。该程序产生的图像有许多重叠的房间。贝娄(Bellow)是应该处理相交检查以及将房间放置到tilemap上的类
public int XSize, YSize;
private Cell[ , ] cells;
private List<Room> rooms;
public Tilemap(int xSize, int ySize)
{
XSize = xSize;
YSize = ySize;
rooms = new List<Room>();
cells = new Cell[XSize, YSize];
for (int y = 0; y < YSize; y++)
{
for (int x = 0; x < XSize; x++)
{
cells[x, y].type = CellType.Empty;
}
}
for (int i = 0; i < 10; i++)
{
GenerateRandomRoomSafe(10);
}
}
private Room GetRoomBounds()
{
Utils.Int2 min = new Utils.Int2(0, 0);
Utils.Int2 max = new Utils.Int2(XSize,YSize);
Utils.Int2 q1 = Utils.GetRandomCoords(min, max);
max.X = XSize - 1 - q1.X;
max.Y = YSize - 1 - q1.Y;
Utils.Int2 siz = Utils.GetRandomCoords(min, max);
Room check = new Room(q1.X, q1.Y, siz.X, siz.Y);
return check;
}
public void GenerateRandomRoomSafe(int maxTries)
{
Room check = new Room(0, 0, 0, 0);
bool isValid = false;
int tries = 0;
if (rooms.Count == 0)
{
isValid = true;
check = GetRoomBounds();
tries = 1;
}
else
{
while (!isValid && tries < maxTries)
{
check = GetRoomBounds();
for (int i = 0; i < rooms.Count; i++)
{
if (!rooms[i].Walls.IntersectsWith(check.Walls))
{
isValid = true;
break;
}
}
tries++;
}
}
if (isValid)
{
Console.WriteLine(check + " was placed after " + tries + " tries");
PlaceRoomUnsafe(check);
}
}
public void PlaceRoomUnsafe(Room r)
{
for (int y = r.Walls.Y; y <= r.Walls.Y + r.Walls.Height; y++)
{
cells[r.Walls.X, y].type = CellType.Wall;
}
for (int y = r.Walls.Y; y <= r.Walls.Y + r.Walls.Height; y++)
{
cells[r.Walls.X + r.Walls.Width, y].type = CellType.Wall;
}
for (int x = r.Walls.X; x <= r.Walls.X + r.Walls.Width; x++)
{
cells[x, r.Walls.Y].type = CellType.Wall;
}
for (int x = r.Walls.X; x <= r.Walls.X + r.Walls.Width; x++)
{
cells[x, r.Walls.Y + r.Walls.Height].type = CellType.Wall;
}
for (int y = r.Floor.Y; y < r.Floor.Y + r.Floor.Height; y++)
{
for (int x = r.Floor.X; x < r.Floor.X + r.Floor.Width; x++)
{
cells[x, y].type = CellType.Floor;
}
}
rooms.Add(r);
}
public void GenerateRandomRoomUnsafe()
{
Room r = GetRoomBounds();
PlaceRoomUnsafe(r);
}
public int GetCellPixel(int x, int y)
{
return (int) cells[x, y].type;
}
public class Room
{
public Rectangle Walls;
public Rectangle Floor;
public Room(int q1X, int q1Y, int xSize, int ySize)
{
Walls.X = q1X;
Walls.Y = q1Y;
Walls.Width = xSize;
Walls.Height = ySize;
Floor.X = q1X + 1;
Floor.Y = q1Y + 1;
Floor.Width = xSize - 1;
Floor.Height = ySize - 1;
}
public override string ToString()
{
return "[Walls: " + Walls + "\n Floor: " + Floor + "]";
}
}
}
答案 0 :(得分:1)
您在GenerateRandomRoomSafe()
中的逻辑是倒数。
在此代码块中:
while (!isValid && tries < maxTries)
{
check = GetRoomBounds();
for (int i = 0; i < rooms.Count; i++)
{
if (!rooms[i].Walls.IntersectsWith(check.Walls))
{
isValid = true;
break;
}
}
tries++;
}
您的意思是,“如果它不与至少一个房间相交,那么它必须是有效的。”
仅仅是因为它不与当前房间相交,并不意味着它就不会与其他房间相交!
它看起来应该更像:(注意评论)
while (!isValid && tries < maxTries)
{
isValid = true; // assume it's good until proven otherwise
check = GetRoomBounds();
for (int i = 0; i < rooms.Count; i++)
{
if (rooms[i].Walls.IntersectsWith(check.Walls)) // if it DOES intersect...
{
isValid = false; // .. then set valid to false.
break;
}
}
tries++;
}
因此,我们首先假设它是有效的,然后当我们遇到一个与DOES相交的房间时,将valid设置为false并停止for
循环,以便可以尝试另一个随机房间(假设我们没有超过尝试次数)。
它产生的一些地图: