I mostly just worked on getting my map generator working today. While I like the maps it makes there are some leftover artifacts from the generation method and the code is currently slower than I want it but for the first map generator I have ever made it does incredibly well. I also have my bit of code that makes a text file of the map still in so I can continue to test it and see exactly what is going on.
class Map
{
public int Height, Width;
public Tile[,] tile;
public Map(int Height, int Width)
{
this.Height = Height;
this.Width = Width;
this.tile = new Tile[Width, Height];
}
}
class Tile
{
public bool Walkable;
public bool Seethrough;
public bool Room_Wall;
public char Symbol;
public Tile(bool Walkable, bool Seethrough, bool Room_Wall, char Symbol)
{
this.Walkable = Walkable;
this.Seethrough = Seethrough;
this.Room_Wall = Room_Wall;
this.Symbol = Symbol;
}
}
class Map_Generation
{
public Map map;
private Random rand = new Random();
private Rect Previous_Room,Starting_Room, hallway;
private List<Rect> rooms = new List<Rect>();
private int Room_Count, Max_Size,Room_Fit, Hallway_Direction, BadRoom_Count, BackTrack;
private bool Room_Made;
private void New_Room(int x, int y)
{
rooms[Room_Count] = (new Rect(x, y, rand.Next(5, 11), rand.Next(5, 11)));
}
private void New_Room(int x, int y, int w, int h)
{
rooms[Room_Count] = (new Rect(x, y, w, h));
}
private void New_Hallway(int Offset)
{
switch (rand.Next(4))
{
case 0:
hallway = new Rect(rand.Next(Previous_Room.X + 1, Previous_Room.X + Previous_Room.Width - 1), Previous_Room.Y - Offset + 1, 1, Offset);
Hallway_Direction = 0;
break;
case 1:
hallway = new Rect(Previous_Room.X + Previous_Room.Width - 1, rand.Next(Previous_Room.Y + 1, Previous_Room.Y + Previous_Room.Height - 1), Offset, 1);
Hallway_Direction = 1;
break;
case 2:
hallway = new Rect(rand.Next(Previous_Room.X + 1, Previous_Room.X + Previous_Room.Width - 1), Previous_Room.Y + Previous_Room.Height - 1, 1, Offset);
Hallway_Direction = 2;
break;
case 3:
hallway = new Rect(Previous_Room.X - Offset + 1, rand.Next(Previous_Room.Y + 1, Previous_Room.Y + Previous_Room.Height - 1), Offset, 1);
Hallway_Direction = 3;
break;
default:
throw new InvalidOperationException();
}
}
private void Transcribe_Room()
{
for (int a = 0; a < rooms[Room_Count].Height; a++)
{
for (int b = 0; b < rooms[Room_Count].Width; b++)
{
if ((a == 0) || (a == rooms[Room_Count].Height - 1) || (b == 0) || (b == rooms[Room_Count].Width - 1))
{
map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Room_Wall = true;
}
else
{
map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Seethrough = true;
map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Walkable = true;
map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Symbol = '.';
}
}
}
}
private void Transcribe_Hallway()
{
for (int a = 0;a<hallway.Height;a++)
{
for (int b = 0; b < hallway.Width; b++)
{
map.tile[hallway.X + b, hallway.Y + a].Seethrough = true;
map.tile[hallway.X + b, hallway.Y + a].Walkable = true;
map.tile[hallway.X + b, hallway.Y + a].Symbol = '.';
}
}
}
private bool Check_Position()
{
if ((rooms[Room_Count].Y < 1) || (rooms[Room_Count].Y + rooms[Room_Count].Height >= map.Height - 1) || (rooms[Room_Count].X < 1) || (rooms[Room_Count].X + rooms[Room_Count].Width >= map.Width - 1))
{
return false;
}
else
{
for (int a = 0; a < rooms[Room_Count].Height; a++)
{
for (int b = 0; b < rooms[Room_Count].Width; b++)
{
if (map.tile[rooms[Room_Count].X + b, rooms[Room_Count].Y + a].Room_Wall)
{
return false;
}
}
}
return true;
}
}
public Map_Generation(int Height, int Width)
{
this.map = new Map(Height, Width);
this.Max_Size = 600;
for (int a = 0; a < Height; a++) { for (int b = 0; b < Width; b++) { map.tile[a, b] = new Tile(false, false, false, '#'); } }
rooms.Add(new Rect(0, 0, 0, 0));
New_Room((rand.Next(Width - 15,Width - 10)), rand.Next(Height - 15,Height - 10));
Starting_Room = rooms[Room_Count];
Previous_Room = rooms[Room_Count];
Transcribe_Room();
Room_Count++;
while (Room_Count < Max_Size)
{
Room_Made = false;
BackTrack = 1;
Previous_Room = rooms[Room_Count-BackTrack];
rooms.Add(new Rect(0,0,0,0));
while (!Room_Made)
{
New_Hallway(rand.Next(2, 9));
New_Room(0, 0);
switch (Hallway_Direction)
{
case 0:
New_Room(hallway.X - (rooms[Room_Count].Width / 2), hallway.Y - rooms[Room_Count].Height + 1, rooms[Room_Count].Width, rooms[Room_Count].Height);
break;
case 1:
New_Room(hallway.X + hallway.Width - 1, hallway.Y - (rooms[Room_Count].Height / 2), rooms[Room_Count].Width, rooms[Room_Count].Height);
break;
case 2:
New_Room(hallway.X - (rooms[Room_Count].Width / 2), hallway.Y + hallway.Width - 1, rooms[Room_Count].Width, rooms[Room_Count].Height);
break;
case 3:
New_Room(hallway.X - rooms[Room_Count].Width + 1, hallway.Y - (rooms[Room_Count].Height / 2), rooms[Room_Count].Width, rooms[Room_Count].Height);
break;
default:
throw new InvalidOperationException();
}
if (Check_Position())
{
Transcribe_Room();
Transcribe_Hallway();
Room_Made = true;
Room_Count++;
BadRoom_Count = 0;
}
BadRoom_Count++;
if (BadRoom_Count > 20)
{
BackTrack++;
if (BackTrack > Room_Count) { BackTrack = 1; Room_Fit++; }
Previous_Room = rooms[Room_Count - BackTrack];
BadRoom_Count = 0;
}
}
if (Room_Fit >= 50)
{
Max_Size = Room_Count;
}
}
StreamWriter SW = new StreamWriter("Test.txt");
for (int a = 0; a < map.Height; a++)
{
for (int b = 0; b < map.Width; b++)
{
SW.Write(map.tile[a, b].Symbol);
}
SW.WriteLine();
}
SW.Close();
}
}
I spent most of my time working on it trying to get placement working right till I figured out I needed to store all of the rooms instead not. I finally figured it out and decided on using a list which works out quite well for what I needed.
The other thing that took a while was cutting features. I originally was going to have water and lava tiles but I ended up tossing that for this game because I had enough on my hands with just generating a regular map. I still need to add doors to it but this was a purposeful choice to not include it here. The way I have it planned I will need to add them later but that will be easy because I will only need to look for map tiles that are both using the '.' character and have Room_Wall as true.