I've made a fairly simple dungeon generator but now I want to expand on it so that I can procedurally generate a dungeon with irregular shaped rooms. I don't just want any old crazy shapes popping up though, I want to be able to have room types that follow a certain pattern but ultimately have random sizes. I just don't have a clue how to generate rooms that aren't just square.
I have an idea of how to merge squares together to make rooms comprised of other rooms, but I'm more interested in how to get hexagon and octagon shaped rooms, or doughnut-like rooms. My code for generating square rooms is:
public static char[,] GetSquareRoom(int width, int height)
{
char[,] roomLayout_Square;
roomLayout_Square = new char[width, height];
for (int x = 0; x < roomLayout_Square.GetLength(0); x++)
for (int y = 0; y < roomLayout_Square.GetLength(1); y++)
if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
roomLayout_Square[x, y] = '#';
else
roomLayout_Square[x, y] = '.';
return roomLayout_Square;
}
I would like to create more functions like this that will accept a few variables so I can create specific variations of these room-types, so I can input specific number and randomly generated values alike.
:)
Answer
You can create a room that is in the shape of a regular convex polygon with arbitrary sides, size and rotation.
Steps:
- Draw walls by picking pairs of points around a circle and linearly interpolating between them. The number of pairs should equal the number of sides of the shape. You will need to use trig for this.
- Create a floor by filling the shape using some sort of fill algorithm.
You can then create a doughnut shaped room by subtracting a smaller generated room from the center of a larger generated room. You should keep the walls of the smaller generated room though.
Since I found this interesting I went ahead and tried implementing it myself. I would recommend not looking at my code until you have tried to write it yourself though.
public static char[,] RegConvexPolyRoom(int sides, double radius, double rotation)
{
// convert the rotation degrees to radians.
rotation *= Math.PI / 180.0;
// make an array size that is sure to fit the room.
int roomSize = (int) Math.Ceiling(radius*2) + 1;
char[,] room = new char[roomSize, roomSize];
// first we must create the walls of the room.
double rchange = (Math.PI * 2.0) / sides;
for (double r = 0; r < Math.PI * 2; r += rchange)
{
// define first point.
double p1_x = radius + Math.Cos(r + rotation) * radius;
double p1_y = radius + Math.Sin(r + rotation) * radius;
// define second point (rotated 1 iteration further).
double p2_x = radius + Math.Cos(r + rotation + rchange) * radius;
double p2_y = radius + Math.Sin(r + rotation + rchange) * radius;
// get distance between the two points.
double len = Math.Sqrt(Math.Pow(p2_x - p1_x, 2) + Math.Pow(p2_y - p1_y, 2));
// linearly interpolate between the two points and place walls between them.
for (double i = 0; i < 1; i += 1.0 / len)
{
int place_x = (int) Math.Round((1 - i) * p1_x + i * p2_x);
int place_y = (int) Math.Round((1 - i) * p1_y + i * p2_y);
room[place_y, place_x] = '#';
}
}
// now we have to fill the room with a floor.
// this is done using something similar to a scanline algorithm.
for (int scan = 0; scan < roomSize; scan++)
{
int left_x = -1;
int right_x = -1;
bool spaceDetected = false;
for (int i = 0; i < roomSize; i++)
{
if (room[scan, i] == '#')
{
if (!spaceDetected)
left_x = i;
else
{
right_x = i;
break;
}
}
else if (left_x != -1)
spaceDetected = true;
}
if (right_x != -1)
{
for (int i = left_x + 1; i < right_x; i++)
{
room[scan, i] = '.';
}
}
}
return room;
}
Here is a hexagonal room generated with the above method:
##############
#.............#
#..............#
#...............#
#................#
#.................#
#...................#
##...................#
#.....................#
#.......................#
#.......................#
#.......................#
#.....................#
#...................##
#..................#
#.................#
#...............##
#...............#
#..............#
#.............#
##############
No comments:
Post a Comment