-
Notifications
You must be signed in to change notification settings - Fork 150
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
647 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,294 @@ | ||
using UnityEngine; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System; | ||
|
||
public class MapGenerator : MonoBehaviour { | ||
|
||
public int width; | ||
public int height; | ||
|
||
public string seed; | ||
public bool useRandomSeed; | ||
|
||
[Range(0,100)] | ||
public int randomFillPercent; | ||
|
||
int[,] map; | ||
|
||
void Start() { | ||
GenerateMap(); | ||
} | ||
|
||
void Update() { | ||
if (Input.GetMouseButtonDown(0)) { | ||
GenerateMap(); | ||
} | ||
} | ||
|
||
void GenerateMap() { | ||
map = new int[width,height]; | ||
RandomFillMap(); | ||
|
||
for (int i = 0; i < 5; i ++) { | ||
SmoothMap(); | ||
} | ||
|
||
ProcessMap (); | ||
|
||
int borderSize = 1; | ||
int[,] borderedMap = new int[width + borderSize * 2,height + borderSize * 2]; | ||
|
||
for (int x = 0; x < borderedMap.GetLength(0); x ++) { | ||
for (int y = 0; y < borderedMap.GetLength(1); y ++) { | ||
if (x >= borderSize && x < width + borderSize && y >= borderSize && y < height + borderSize) { | ||
borderedMap[x,y] = map[x-borderSize,y-borderSize]; | ||
} | ||
else { | ||
borderedMap[x,y] =1; | ||
} | ||
} | ||
} | ||
|
||
MeshGenerator meshGen = GetComponent<MeshGenerator>(); | ||
meshGen.GenerateMesh(borderedMap, 1); | ||
} | ||
|
||
void ProcessMap() { | ||
List<List<Coord>> wallRegions = GetRegions (1); | ||
int wallThresholdSize = 50; | ||
|
||
foreach (List<Coord> wallRegion in wallRegions) { | ||
if (wallRegion.Count < wallThresholdSize) { | ||
foreach (Coord tile in wallRegion) { | ||
map[tile.tileX,tile.tileY] = 0; | ||
} | ||
} | ||
} | ||
|
||
List<List<Coord>> roomRegions = GetRegions (0); | ||
int roomThresholdSize = 50; | ||
List<Room> survivingRooms = new List<Room> (); | ||
|
||
foreach (List<Coord> roomRegion in roomRegions) { | ||
if (roomRegion.Count < roomThresholdSize) { | ||
foreach (Coord tile in roomRegion) { | ||
map[tile.tileX,tile.tileY] = 1; | ||
} | ||
} | ||
else { | ||
survivingRooms.Add(new Room(roomRegion, map)); | ||
} | ||
} | ||
|
||
ConnectClosestRooms (survivingRooms); | ||
} | ||
|
||
void ConnectClosestRooms(List<Room> allRooms) { | ||
|
||
int bestDistance = 0; | ||
Coord bestTileA = new Coord (); | ||
Coord bestTileB = new Coord (); | ||
Room bestRoomA = new Room (); | ||
Room bestRoomB = new Room (); | ||
bool possibleConnectionFound = false; | ||
|
||
foreach (Room roomA in allRooms) { | ||
possibleConnectionFound = false; | ||
|
||
foreach (Room roomB in allRooms) { | ||
if (roomA == roomB) { | ||
continue; | ||
} | ||
if (roomA.IsConnected(roomB)) { | ||
possibleConnectionFound = false; | ||
break; | ||
} | ||
|
||
for (int tileIndexA = 0; tileIndexA < roomA.edgeTiles.Count; tileIndexA ++) { | ||
for (int tileIndexB = 0; tileIndexB < roomB.edgeTiles.Count; tileIndexB ++) { | ||
Coord tileA = roomA.edgeTiles[tileIndexA]; | ||
Coord tileB = roomB.edgeTiles[tileIndexB]; | ||
int distanceBetweenRooms = (int)(Mathf.Pow (tileA.tileX-tileB.tileX,2) + Mathf.Pow (tileA.tileY-tileB.tileY,2)); | ||
|
||
if (distanceBetweenRooms < bestDistance || !possibleConnectionFound) { | ||
bestDistance = distanceBetweenRooms; | ||
possibleConnectionFound = true; | ||
bestTileA = tileA; | ||
bestTileB = tileB; | ||
bestRoomA = roomA; | ||
bestRoomB = roomB; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (possibleConnectionFound) { | ||
CreatePassage(bestRoomA, bestRoomB, bestTileA, bestTileB); | ||
} | ||
} | ||
} | ||
|
||
void CreatePassage(Room roomA, Room roomB, Coord tileA, Coord tileB) { | ||
Room.ConnectRooms (roomA, roomB); | ||
Debug.DrawLine (CoordToWorldPoint (tileA), CoordToWorldPoint (tileB), Color.green, 100); | ||
} | ||
|
||
Vector3 CoordToWorldPoint(Coord tile) { | ||
return new Vector3 (-width / 2 + .5f + tile.tileX, 2, -height / 2 + .5f + tile.tileY); | ||
} | ||
|
||
List<List<Coord>> GetRegions(int tileType) { | ||
List<List<Coord>> regions = new List<List<Coord>> (); | ||
int[,] mapFlags = new int[width,height]; | ||
|
||
for (int x = 0; x < width; x ++) { | ||
for (int y = 0; y < height; y ++) { | ||
if (mapFlags[x,y] == 0 && map[x,y] == tileType) { | ||
List<Coord> newRegion = GetRegionTiles(x,y); | ||
regions.Add(newRegion); | ||
|
||
foreach (Coord tile in newRegion) { | ||
mapFlags[tile.tileX, tile.tileY] = 1; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return regions; | ||
} | ||
|
||
List<Coord> GetRegionTiles(int startX, int startY) { | ||
List<Coord> tiles = new List<Coord> (); | ||
int[,] mapFlags = new int[width,height]; | ||
int tileType = map [startX, startY]; | ||
|
||
Queue<Coord> queue = new Queue<Coord> (); | ||
queue.Enqueue (new Coord (startX, startY)); | ||
mapFlags [startX, startY] = 1; | ||
|
||
while (queue.Count > 0) { | ||
Coord tile = queue.Dequeue(); | ||
tiles.Add(tile); | ||
|
||
for (int x = tile.tileX - 1; x <= tile.tileX + 1; x++) { | ||
for (int y = tile.tileY - 1; y <= tile.tileY + 1; y++) { | ||
if (IsInMapRange(x,y) && (y == tile.tileY || x == tile.tileX)) { | ||
if (mapFlags[x,y] == 0 && map[x,y] == tileType) { | ||
mapFlags[x,y] = 1; | ||
queue.Enqueue(new Coord(x,y)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return tiles; | ||
} | ||
|
||
bool IsInMapRange(int x, int y) { | ||
return x >= 0 && x < width && y >= 0 && y < height; | ||
} | ||
|
||
|
||
void RandomFillMap() { | ||
if (useRandomSeed) { | ||
seed = Time.time.ToString(); | ||
} | ||
|
||
System.Random pseudoRandom = new System.Random(seed.GetHashCode()); | ||
|
||
for (int x = 0; x < width; x ++) { | ||
for (int y = 0; y < height; y ++) { | ||
if (x == 0 || x == width-1 || y == 0 || y == height -1) { | ||
map[x,y] = 1; | ||
} | ||
else { | ||
map[x,y] = (pseudoRandom.Next(0,100) < randomFillPercent)? 1: 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void SmoothMap() { | ||
for (int x = 0; x < width; x ++) { | ||
for (int y = 0; y < height; y ++) { | ||
int neighbourWallTiles = GetSurroundingWallCount(x,y); | ||
|
||
if (neighbourWallTiles > 4) | ||
map[x,y] = 1; | ||
else if (neighbourWallTiles < 4) | ||
map[x,y] = 0; | ||
|
||
} | ||
} | ||
} | ||
|
||
int GetSurroundingWallCount(int gridX, int gridY) { | ||
int wallCount = 0; | ||
for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX ++) { | ||
for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY ++) { | ||
if (IsInMapRange(neighbourX,neighbourY)) { | ||
if (neighbourX != gridX || neighbourY != gridY) { | ||
wallCount += map[neighbourX,neighbourY]; | ||
} | ||
} | ||
else { | ||
wallCount ++; | ||
} | ||
} | ||
} | ||
|
||
return wallCount; | ||
} | ||
|
||
struct Coord { | ||
public int tileX; | ||
public int tileY; | ||
|
||
public Coord(int x, int y) { | ||
tileX = x; | ||
tileY = y; | ||
} | ||
} | ||
|
||
|
||
class Room { | ||
public List<Coord> tiles; | ||
public List<Coord> edgeTiles; | ||
public List<Room> connectedRooms; | ||
public int roomSize; | ||
|
||
public Room() { | ||
} | ||
|
||
public Room(List<Coord> roomTiles, int[,] map) { | ||
tiles = roomTiles; | ||
roomSize = tiles.Count; | ||
connectedRooms = new List<Room>(); | ||
|
||
edgeTiles = new List<Coord>(); | ||
foreach (Coord tile in tiles) { | ||
for (int x = tile.tileX-1; x <= tile.tileX+1; x++) { | ||
for (int y = tile.tileY-1; y <= tile.tileY+1; y++) { | ||
if (x == tile.tileX || y == tile.tileY) { | ||
if (map[x,y] == 1) { | ||
edgeTiles.Add(tile); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
public static void ConnectRooms(Room roomA, Room roomB) { | ||
roomA.connectedRooms.Add (roomB); | ||
roomB.connectedRooms.Add (roomA); | ||
} | ||
|
||
public bool IsConnected(Room otherRoom) { | ||
return connectedRooms.Contains(otherRoom); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.