Day 7b:
A couple of hours later and I had another go. Went back over the code for generating the maze and found some bugs. It was stopping a bit early making the rooms. Looks like some defects in the maze generation, repeated cubicles down the sides etc…
Also built new template objects. A simple room with four posts in the corners, and a door/wall that can fit between the posts, and be rotated to any of the four positions.
It is much easier to build up the maze now. Just spawn a room for every Room[x,y] class, and build the walls as before.
The navigation stuff wigs out if the maze is over about 15x15 rooms though, and drop to <1FPS. That’s a later issue though.
public class scenescripts : MonoBehaviour {
//public NPCmove tmpobject; //Set the object to spawn in properties
//public int NPC_Count; //Set number of ojbets to spawn in properties
//public int x_range; // Translation X range
//public int y_range; // Translation Y range
public int Maze_Segments_x = 10;
public int Maze_Segments_y = 10;
Room[,] Rooms;
public float Map_Scale_factor = 2;
public GameObject room_template;
public GameObject wall_template;
public GameObject goal;
float counter;
public float Map_Offset_x = 5f;
public float Map_Offset_y = 5f;
public float Map_Offset_z = 0.5f;
// Use this for initialization
void Start() {
//for (int i = 0; i < NPC_Count; i++)
//{
// tmpobject.transform.Translate(new Vector3(Random.Range(-x_range, x_range), 0, Random.Range(-y_range, y_range)));
// Instantiate(tmpobject);
//}
genMaze();
}
// Update is called once per frame
void Update() {
}
class Room
{
public Wall Up;
public Wall Down;
public Wall Left;
public Wall Right;
public bool isVisited;
}
class Wall
{
public Room Room1;
public Room Room2;
public bool passage;
public Wall(Room Room1,Room Room2 )
{
this.passage = false;
this.Room1 = Room1;
this.Room2 = Room2;
}
}
void genMaze()
{
//Array of cells set to right size
Rooms = new Room[Maze_Segments_x, Maze_Segments_y];
List<Wall> Walls = new List<Wall>();
int x, y;
//Build grid of rooms
for (y = 0; y < Maze_Segments_y; y++)
{
for (x = 0; x < Maze_Segments_x; x++)
{
Room tmproom = new Room();
tmproom.isVisited = false;
Rooms[x, y] = tmproom;
}
}
//Run back over array and create walls between all the rooms, putting in the references to rooms etc.
for (y = 0; y < Maze_Segments_y; y++)
{
for (x = 0; x < Maze_Segments_x; x++)
{
// fixed some bugs here in map generation
if (x == 0)
{
Rooms[x, y].Left = new Wall(Rooms[x, y], null);
}
else if (x == Maze_Segments_x - 1)
{
Rooms[x, y].Right = new Wall(Rooms[x, y], null);
}
else
{
Wall tmpwall = new Wall(Rooms[x, y], Rooms[x + 1, y]);
Rooms[x, y].Right = tmpwall;
Rooms[x + 1, y].Left = tmpwall;
}
if (y == 0)
{
Rooms[x, y].Up = new Wall(Rooms[x, y], null);
}
else if (y == Maze_Segments_x - 1)
{
Rooms[x, y].Down = new Wall(Rooms[x, y], null);
}
else
{
Rooms[x, y].Down = new Wall(Rooms[x, y], null);
Wall tmpwall = new Wall(Rooms[x, y], Rooms[x, y + 1]);
Rooms[x, y].Down = tmpwall;
Rooms[x, y + 1].Up = tmpwall;
}
}
}
/*
Modified Prim's algorithm from Wikipedia
1. Start with a grid full of walls.
2. Pick a cell, mark it as part of the maze. Add the walls of the cell to the wall list.
3. While there are walls in the list:
a. Pick a random wall from the list. If only one of the two cells that the wall divides is visited, then:
i. Make the wall a passage and mark the unvisited cell as part of the maze.
ii. Add the neighboring walls of the cell to the wall list.
b. Remove the wall from the list.
*/
//2. Pick a cell, mark it as part of the maze. Add the walls of the cell to the wall list.
// Need to pick even index inside the maze
// TODO: Should probably just pick 1,1 or something known!
x = Random.Range(1, (Maze_Segments_x - 1) / 2) * 2;
y = Random.Range(1, (Maze_Segments_y - 1) / 2) * 2;
Rooms[x, y].isVisited = true;
Walls.Add(Rooms[x, y].Up);
Walls.Add(Rooms[x, y].Down);
Walls.Add(Rooms[x, y].Left);
Walls.Add(Rooms[x, y].Right);
// 3. While there are walls in the list:
do
{
int r = Random.Range(0, Walls.Count - 1);
if (Walls[r] == null) { }
else if (Walls[r].Room1 == null || Walls[r].Room2 == null) { }
else if (Walls[r].Room1.isVisited ^ Walls[r].Room2.isVisited) //either visited but not both
{
Walls[r].passage = true;
if (!Walls[r].Room1.isVisited)
{
Walls[r].Room1.isVisited = true;
if (!Walls.Contains(Walls[r].Room1.Up)) Walls.Add(Walls[r].Room1.Up);
if (!Walls.Contains(Walls[r].Room1.Down)) Walls.Add(Walls[r].Room1.Down);
if (!Walls.Contains(Walls[r].Room1.Left)) Walls.Add(Walls[r].Room1.Left);
if (!Walls.Contains(Walls[r].Room1.Right)) Walls.Add(Walls[r].Room1.Right);
}
else
{
Walls[r].Room2.isVisited = true;
if (!Walls.Contains(Walls[r].Room2.Up)) Walls.Add(Walls[r].Room2.Up);
if (!Walls.Contains(Walls[r].Room2.Down)) Walls.Add(Walls[r].Room2.Down);
if (!Walls.Contains(Walls[r].Room2.Left)) Walls.Add(Walls[r].Room2.Left);
if (!Walls.Contains(Walls[r].Room2.Right)) Walls.Add(Walls[r].Room2.Right);
}
}
Walls.Remove(Walls[r]);
} while (Walls.Count > 0);
//Done forming maze
GameObject tmpobject;
//Build maze out of 3d objects
for (y = 0; y < Maze_Segments_y; y++)
{
for (x = 0; x < Maze_Segments_x; x++)
{
//No room! Shouldnt happen anymore.
if (Rooms[x,y]==null) continue;
tmpobject = Instantiate(room_template);
tmpobject.transform.Translate(new Vector3(Map_Offset_x + (x * Map_Scale_factor) + Map_Scale_factor / 2, Map_Offset_z, Map_Offset_y + (y * Map_Scale_factor) + Map_Scale_factor / 2));
if (Rooms[x, y].Up != null && !Rooms[x, y].Up.passage)
{
tmpobject = Instantiate(wall_template);
tmpobject.transform.Translate(new Vector3(Map_Offset_x + (x * Map_Scale_factor) + Map_Scale_factor / 2, Map_Offset_z, Map_Offset_y + (y * Map_Scale_factor) + Map_Scale_factor / 2));
tmpobject.transform.Rotate(new Vector3(0, 270, 0));
}
if (Rooms[x, y].Right != null && !Rooms[x, y].Right.passage && x == Maze_Segments_x - 1)
{
tmpobject = Instantiate(wall_template);
tmpobject.transform.Translate(new Vector3(Map_Offset_x + (x * Map_Scale_factor) + Map_Scale_factor / 2, Map_Offset_z, Map_Offset_y + (y * Map_Scale_factor) + Map_Scale_factor / 2));
tmpobject.transform.Rotate(new Vector3(0, 180, 0));
}
if (Rooms[x, y].Down != null && !Rooms[x, y].Down.passage && y == Maze_Segments_y - 1)
{
tmpobject = Instantiate(wall_template);
tmpobject.transform.Translate(new Vector3(Map_Offset_x + (x * Map_Scale_factor) + Map_Scale_factor / 2, Map_Offset_z, Map_Offset_y + (y * Map_Scale_factor) + Map_Scale_factor / 2));
tmpobject.transform.Rotate(new Vector3(0, 90, 0));
}
if (Rooms[x, y].Left != null && !Rooms[x, y].Left.passage)
{
tmpobject = Instantiate(wall_template);
tmpobject.transform.Translate(new Vector3(Map_Offset_x + (x * Map_Scale_factor) + Map_Scale_factor / 2, Map_Offset_z, Map_Offset_y + (y * Map_Scale_factor) + Map_Scale_factor / 2));
tmpobject.transform.Rotate(new Vector3(0, 0, 0));
}
}
}
goal.transform.Translate(new Vector3(Map_Offset_x + ((Maze_Segments_x-1) * Map_Scale_factor)-1, 0, Map_Offset_y + ((Maze_Segments_y-1) * Map_Scale_factor)-1));
}
}