Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- public class MapGenerator {
- public Room[,] rooms;
- public List<Room> path = new List<Room>();
- private float[] entranceNumberChances = { .40f, .35f, .25f, .20f }; // 50% chance for 1 door, 25% chance for 2 doors, 15% chance for 3 doors, 10% chance for 4 doors
- private readonly int[] size;
- enum directions {
- UP,
- DOWN,
- LEFT,
- RIGHT
- }
- private System.Random random = new System.Random();
- public MapGenerator(int[] size, int[] roomSize) {
- rooms = new Room[size[0], size[1]];
- this.size = size;
- for (int i = 0; i < size[0]; i++) {
- for (int j = 0; j < size[1]; j++) {
- Room room = new Room(roomSize, new int[] { i, j });
- rooms[i, j] = room;
- }
- }
- DepthFirstSearch(ref rooms[0, 0]);
- foreach (Room r in rooms) {
- r.visited = false;
- }
- Room startRoom = rooms[0, 0];
- Room endRoom = rooms[size[0] - 1, size[1] - 1];
- SolveMaze(ref startRoom, ref endRoom);
- SetPathIDs(ref startRoom, ref endRoom);
- ClearRooms();
- for (int i = 0; i < size[0]; i++) {
- for (int j = 0; j < size[1]; j++) {
- GenerateWallSValues(rooms[i, j]);
- }
- }
- }
- // 1f = wall, 0f = wood, .5f = nothing
- public void GenerateWallSValues(Room room) {
- float[,] sValuesWalls = new float[room.size[0], room.size[1]]; // sValues = Special Values
- for (int i = 0; i < room.size[0]; i++) {
- for (int j = 0; j < room.size[1]; j++) {
- // Edge
- if (room.solution) {
- if (i == 0 || j == 0 || i == room.size[0] - 1 || j == room.size[1] - 1) {
- sValuesWalls[i, j] = 1f;
- if (i == 0 && room.entranceArray[3]) {
- if (j != 0 && j != room.size[1] - 1) sValuesWalls[i, j] = 0f;
- else if (j == 0 && room.entranceArray[2]) sValuesWalls[i, j] = 0f;
- else if (j == room.size[1] - 1 && room.entranceArray[0]) sValuesWalls[i, j] = 0f;
- }
- if (i == room.size[0] - 1 && room.entranceArray[1]) {
- if (j != 0 && j != room.size[1] - 1) sValuesWalls[i, j] = 0f;
- else if (j == 0 && room.entranceArray[2]) sValuesWalls[i, j] = 0f;
- else if (j == room.size[1] - 1 && room.entranceArray[0]) sValuesWalls[i, j] = 0f;
- }
- if (j == 0 && room.entranceArray[2]) {
- if (i != 0 && i != room.size[0] - 1) sValuesWalls[i, j] = 0f;
- }
- if (j == room.size[1] - 1 && room.entranceArray[0]) {
- if (i != 0 && i != room.size[0] - 1) sValuesWalls[i, j] = 0f;
- }
- } else {
- sValuesWalls[i, j] = 0f;
- }
- } else {
- sValuesWalls[i, j] = .5f;
- }
- }
- }
- #region Entrances
- /*
- float e = UnityEngine.Random.Range(0f, 1f);
- int entrances = 0;
- for (int i = entranceNumberChances.Length - 1; i >= 0; i--) {
- if (e <= entranceNumberChances[i] || i == 0) {
- entrances = i + 1;
- break;
- }
- }
- Room[] aRooms = GetAdjacentRooms(room);
- for (int i = 0; i < aRooms.Length; i++) {
- if (aRooms[i] == null) continue;
- bool entrance = aRooms[i].entranceArray[GetOppositeDirection(i)];
- if (aRooms[i].entrances > 0 && entrance) {
- Debug.Log(i + " " + GetOppositeDirection(i));
- room.entranceArray[i] = true;
- room.entrances = Math.Min(4, room.entrances + 1);
- }
- }
- entrances = Math.Min(4, entrances + room.entrances);
- for (int i = 0; i < entrances - room.entrances; i++) {
- directions dir;
- do {
- dir = RandomDirection();
- } while (room.entranceArray[IntFromDirection(dir)] != false);
- room.entranceArray[IntFromDirection(dir)] = true;
- room.entrances++;
- }
- // Empty out parts of the walls to form entrances
- for (int i = 0; i < room.entranceArray.Length; i++) {
- if (room.entranceArray[i] == true) {
- switch (i) {
- case 0:
- sValuesWalls[(int) (room.size[0] / 2), 0] = 0f;
- break;
- case 1:
- sValuesWalls[0, (int) room.size[1] / 2] = 0f;
- break;
- case 2:
- sValuesWalls[(int) (room.size[0] / 2), room.size[1] - 1] = 0f;
- break;
- case 3:
- sValuesWalls[room.size[0] - 1, (int) (room.size[1] / 2)] = 0f;
- break;
- default:
- break;
- }
- }
- }/*/
- #endregion
- FillWalls(room, sValuesWalls);
- }
- // A recersive Depth First Search. Basically it randomly goes as far as it can go, and once it can't go any further it goes a node back and branches out from there.
- // This function produces the initial maze that is then simplified down to the simplest path.
- public void DepthFirstSearch(ref Room node) {
- if (node.visited) return;
- List<Room> aRooms = GetAdjacentRoomsList(node);
- node.visited = true;
- foreach (int i in Enumerable.Range(0, aRooms.Count).OrderBy(x => random.Next())) {
- Room child = aRooms[i];
- if (!child.visited) {
- int dir = IntFromDirection(GetDirection(node, child));
- node.entranceArray[dir] = true;
- child.entranceArray[GetOppositeDirection(dir)] = true;
- DepthFirstSearch(ref child);
- }
- }
- }
- public bool SolveMaze(ref Room node, ref Room goal) {
- if (node.visited) return false;
- node.visited = true;
- for (int i = 0; i < node.entranceArray.Length; i++) {
- if (node.entranceArray[i]) {
- Room child = GetRoom(node, DirectionFromInt(i));
- if (child.visited) continue;
- if (child == goal || SolveMaze(ref child, ref goal)) {
- node.entranceArray = new bool[] { false, false, false, false };
- node.entranceArray[i] = true;
- node.pathNext = child;
- child.pathPrevious = node;
- child.entranceArray[GetOppositeDirection(i)] = true;
- node.solution = true;
- child.solution = true;
- return true;
- }
- }
- }
- return false;
- }
- public void ClearRooms() {
- foreach (Room currentRoom in path) {
- List<Room> aRooms = GetAdjacentRoomsList(currentRoom);
- foreach (Room room in aRooms) {
- int diff = Math.Abs(room.pathId - currentRoom.pathId);
- if (room.solution && !room.cleared && diff > 1 && diff <= 5) {
- directions dir = GetDirection(room, currentRoom);
- room.entranceArray[IntFromDirection(dir)] = true;
- currentRoom.entranceArray[GetOppositeDirection(IntFromDirection(dir))] = true;
- currentRoom.cleared = true;
- Debug.Log(String.Format("({0}, {1}) ({2}, {3})", room.position[0], room.position[1], currentRoom.position[0], currentRoom.position[1]));
- }
- }
- }
- }
- public void SetPathIDs(ref Room start, ref Room finish) {
- int pathId = 0;
- Room currentRoom = start;
- do {
- currentRoom.pathId = pathId++;
- path.Add(currentRoom);
- currentRoom = currentRoom.pathNext;
- } while (currentRoom.pathNext != null);
- }
- public void FillWalls(Room room, float[,] sValues) {
- for (int i = 0; i < room.size[0]; i++) {
- for (int j = 0; j < room.size[1]; j++) {
- if (sValues[i, j] == 1f) {
- Board.AddTile(Board.self.wallPrefab, new int[] { i + (room.position[0] * room.size[0]), j + (room.position[1] * room.size[1]) });
- } else if (sValues[i, j] == 0f) {
- Board.AddTile(Board.self.woodPrefab, new int[] { i + (room.position[0] * room.size[0]), j + (room.position[1] * room.size[1]) });
- }
- }
- }
- }
- private directions RandomDirection() {
- var v = Enum.GetValues(typeof(directions));
- return (directions) v.GetValue(random.Next(v.Length));
- }
- private int GetOppositeDirection(int dir) {
- switch (dir) {
- case 0:
- return 2;
- case 1:
- return 3;
- case 2:
- return 0;
- case 3:
- return 1;
- default:
- return 0;
- }
- }
- private int IntFromDirection(directions dir) {
- switch (dir) {
- case directions.UP:
- return 0;
- case directions.RIGHT:
- return 1;
- case directions.DOWN:
- return 2;
- case directions.LEFT:
- return 3;
- default:
- return 0;
- }
- }
- private directions DirectionFromInt(int dir) {
- switch (dir) {
- case 0:
- return directions.UP;
- case 1:
- return directions.RIGHT;
- case 2:
- return directions.DOWN;
- case 3:
- return directions.LEFT;
- default:
- return directions.UP;
- }
- }
- private Room[] GetAdjacentRooms(Room room) {
- // (Clockwise)
- return new Room[] { GetRoom(room, directions.UP), // UP
- GetRoom(room, directions.RIGHT), // RIGHT
- GetRoom(room, directions.DOWN), // DOWN
- GetRoom(room, directions.LEFT)}; // LEFT
- }
- private List<Room> GetAdjacentRoomsList(Room room) {
- List<Room> r = new List<Room>();
- Room r1 = GetRoom(room, directions.UP);
- Room r2 = GetRoom(room, directions.RIGHT);
- Room r3 = GetRoom(room, directions.DOWN);
- Room r4 = GetRoom(room, directions.LEFT);
- if (r1 != null) r.Add(r1);
- if (r2 != null) r.Add(r2);
- if (r3 != null) r.Add(r3);
- if (r4 != null) r.Add(r4);
- return r;
- }
- private directions GetDirection(Room r1, Room compare) {
- int xDiff = compare.position[0] - r1.position[0];
- int yDiff = compare.position[1] - r1.position[1];
- if (xDiff >= 1) return directions.RIGHT;
- else if (xDiff <= -1) return directions.LEFT;
- if (yDiff >= 1) return directions.UP;
- else return directions.DOWN;
- }
- private Room GetRoom(Room room, directions dir) {
- if (room == null) return null;
- int x = room.position[0];
- int y = room.position[1];
- switch (dir) {
- case directions.DOWN:
- return rooms[x, Math.Max(0, y - 1)];
- case directions.RIGHT:
- return rooms[Math.Min(size[0] - 1, x + 1), y];
- case directions.UP:
- return rooms[x, Math.Min(size[1] - 1, y + 1)];
- case directions.LEFT:
- return rooms[Math.Max(0, x - 1), y];
- default:
- return room;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement