void SetTileMaterial(E_TileMaterialType tileMaterialType, out Transform[] floorTiles, out Transform[] wallTiles) { switch (tileMaterialType) { case E_TileMaterialType.dirt: floorTiles = tile_dirt_floor; wallTiles = tile_dirt_wall; break; default: floorTiles = tile_dirt_floor; wallTiles = tile_dirt_wall; break; } }
//create a room from a startpoint(leftdown), width, and length bool CreateRoom(int startX, int startZ, int extendX, int extendZ, E_RoomType roomType, E_TileMaterialType tileMaterialType) { if (extendX <= 1 || extendZ <= 1) //room has wall so it need enough size { return(false); } if (startX + extendX > dungeonWidth || startZ + extendZ > dungeonLength || startX < 0 || startZ < 0) { return(false); // out of the dungeon bound } //enough space in case of wall thickness for (int i = -1; i < extendX + 1; i++) { for (int j = -1; j < extendZ + 1; j++) { if (startX + i < 0 || startX + i > layerTile.GetLength(0) - 1 || startZ + j < 0 || startZ + j > layerTile.GetLength(1) - 1) { return(false); //防止数组越界 } if (layerTile[startX + i, startZ + j] != E_TileType.empty) { return(false); //not enough space for room } } } //material type Transform[] floorTiles, wallTiles; SetTileMaterial(tileMaterialType, out floorTiles, out wallTiles); //generate room root MapElement currentRoomScript = GenerateElementRoot(E_MapElementType.Room, startX, startZ); currentRoomScript.tile = new Transform[extendX, extendZ]; currentRoomScript.hasItem = new bool[extendX, extendZ]; currentRoomScript.walls = new List <Transform>(); for (int i = 0; i < extendX; i++) { for (int j = 0; j < extendZ; j++) { currentRoomScript.tile[i, j] = RandomlyCreateTile(i, j, floorTiles); currentRoomScript.hasItem[i, j] = false; if (i + j == 0) { //corner leftdown layerTile[startX + i, startZ + j] = E_TileType.corner_LeftDown; RandomlyCreateWall(i, j, wallTiles, E_Direction.Left, currentRoomScript.walls); RandomlyCreateWall(i, j, wallTiles, E_Direction.Down, currentRoomScript.walls); } else if (i + j == extendX + extendZ - 2) { //corner rightup layerTile[startX + i, startZ + j] = E_TileType.corner_RightUp; RandomlyCreateWall(i, j, wallTiles, E_Direction.Right, currentRoomScript.walls); RandomlyCreateWall(i, j, wallTiles, E_Direction.Up, currentRoomScript.walls); } else if (i - j == extendX - 1) { //corner rightdown layerTile[startX + i, startZ + j] = E_TileType.corner_RightDown; RandomlyCreateWall(i, j, wallTiles, E_Direction.Right, currentRoomScript.walls); RandomlyCreateWall(i, j, wallTiles, E_Direction.Down, currentRoomScript.walls); } else if (j - i == extendZ - 1) { //corner leftup layerTile[startX + i, startZ + j] = E_TileType.corner_LeftUp; RandomlyCreateWall(i, j, wallTiles, E_Direction.Left, currentRoomScript.walls); RandomlyCreateWall(i, j, wallTiles, E_Direction.Up, currentRoomScript.walls); } else if (i == 0) { //wall left layerTile[startX + i, startZ + j] = E_TileType.wall_left; RandomlyCreateWall(i, j, wallTiles, E_Direction.Left, currentRoomScript.walls); } else if (j == 0) { //wall down layerTile[startX + i, startZ + j] = E_TileType.wall_down; RandomlyCreateWall(i, j, wallTiles, E_Direction.Down, currentRoomScript.walls); } else if (i == extendX - 1) { //wall right layerTile[startX + i, startZ + j] = E_TileType.wall_right; RandomlyCreateWall(i, j, wallTiles, E_Direction.Right, currentRoomScript.walls); } else if (j == extendZ - 1) { //wall up layerTile[startX + i, startZ + j] = E_TileType.wall_up; RandomlyCreateWall(i, j, wallTiles, E_Direction.Up, currentRoomScript.walls); } else { //floor layerTile[startX + i, startZ + j] = E_TileType.floor; } } } currentRoomScript.exitCount = 0; currentRoomScript.roomType = roomType; // switch (roomType) { // case E_RoomType.normal: // // break; // default: // break; // } return(true); }
bool CreateCorridorFromMapElement(Transform mapElem, E_TileMaterialType tileMaterialType, int index = -1) { List <Transform> chosenWalls = mapElem.GetComponent <MapElement> ().walls; Transform testedWall; if (index == -1) { testedWall = chosenWalls[Random.Range(0, chosenWalls.Count - 1)]; } else { testedWall = chosenWalls[index]; } int wallX = Mathf.RoundToInt(testedWall.position.x) / tileWidth; int wallZ = Mathf.RoundToInt(testedWall.position.z) / tileWidth; int corridorStartX, corridorStartZ; //如果处于房间拐角则不能创建 if (layerTile[wallX, wallZ] == E_TileType.corner_LeftDown || layerTile[wallX, wallZ] == E_TileType.corner_LeftUp || layerTile[wallX, wallZ] == E_TileType.corner_RightDown || layerTile[wallX, wallZ] == E_TileType.corner_RightUp) { return(false); } E_Direction WallDir = CheckWallDirection(testedWall); //corridor direction if (WallDir == E_Direction.Unset) { return(false); } switch (WallDir) { case E_Direction.Up: corridorStartX = wallX; corridorStartZ = wallZ + 1; break; case E_Direction.Down: corridorStartX = wallX; corridorStartZ = wallZ - 1; break; case E_Direction.Left: corridorStartX = wallX - 1; corridorStartZ = wallZ; break; case E_Direction.Right: corridorStartX = wallX + 1; corridorStartZ = wallZ; break; default: corridorStartX = wallX; corridorStartZ = wallZ; return(false); } //random corridor length int corridorLength = Random.Range(minCorridorLength, maxCorridorLength); if (CreateCorridor(corridorStartX, corridorStartZ, corridorLength, WallDir, tileMaterialType)) { mapElem.GetComponent <MapElement>().exitCount++; chosenWalls.Remove(testedWall); //新建立的corridor将保存被隐藏的wall layerCorridors[layerCorridors.Count - 1].GetComponent <MapElement>().removedWall = testedWall; testedWall.gameObject.SetActive(false); return(true); } else { return(false); } }
//create a corridor from a startpoint and dir bool CreateCorridor(int corridorStartX, int corridorStartZ, int corridorLength, E_Direction corridorDir, E_TileMaterialType tileMaterialType) { int corridorDirDeltaX, corridorDirDeltaZ; if (corridorDir == E_Direction.Unset) { return(false); } switch (corridorDir) { case E_Direction.Up: corridorDirDeltaX = 0; corridorDirDeltaZ = 1; break; case E_Direction.Down: corridorDirDeltaX = 0; corridorDirDeltaZ = -1; break; case E_Direction.Left: corridorDirDeltaX = -1; corridorDirDeltaZ = 0; break; case E_Direction.Right: corridorDirDeltaX = 1; corridorDirDeltaZ = 0; break; default: corridorDirDeltaX = 0; corridorDirDeltaZ = 0; return(false); } for (int i = 0; i < corridorLength + 1; i++) { //check for enough space switch (corridorDir) { case E_Direction.Up: if (corridorStartX - 1 < 0 || corridorStartX + 1 > layerTile.GetLength(0) - 1 || corridorStartZ + i < 0 || corridorStartZ + i > layerTile.GetLength(1) - 1) { return(false); } if (layerTile[corridorStartX, corridorStartZ + i] != E_TileType.empty || layerTile[corridorStartX + 1, corridorStartZ + i] != E_TileType.empty || layerTile[corridorStartX - 1, corridorStartZ + i] != E_TileType.empty) { return(false); } break; case E_Direction.Down: if (corridorStartX - 1 < 0 || corridorStartX + 1 > layerTile.GetLength(0) - 1 || corridorStartZ - i < 0 || corridorStartZ - i > layerTile.GetLength(1) - 1) { return(false); } if (layerTile[corridorStartX, corridorStartZ - i] != E_TileType.empty || layerTile[corridorStartX + 1, corridorStartZ - i] != E_TileType.empty || layerTile[corridorStartX - 1, corridorStartZ - i] != E_TileType.empty) { return(false); } break; case E_Direction.Left: if (corridorStartX - i < 0 || corridorStartX - i > layerTile.GetLength(0) - 1 || corridorStartZ - 1 < 0 || corridorStartZ + 1 > layerTile.GetLength(1) - 1) { return(false); } if (layerTile[corridorStartX - i, corridorStartZ] != E_TileType.empty || layerTile[corridorStartX - i, corridorStartZ + 1] != E_TileType.empty || layerTile[corridorStartX - i, corridorStartZ - 1] != E_TileType.empty) { return(false); } break; case E_Direction.Right: if (corridorStartX + i < 0 || corridorStartX + i > layerTile.GetLength(0) - 1 || corridorStartZ - 1 < 0 || corridorStartZ + 1 > layerTile.GetLength(1) - 1) { return(false); } if (layerTile[corridorStartX + i, corridorStartZ] != E_TileType.empty || layerTile[corridorStartX + i, corridorStartZ + 1] != E_TileType.empty || layerTile[corridorStartX + i, corridorStartZ - 1] != E_TileType.empty) { return(false); } break; default: break; } } //material type Transform[] floorTiles, wallTiles; SetTileMaterial(tileMaterialType, out floorTiles, out wallTiles); //generate corridor root MapElement currentCorridorScript = GenerateElementRoot(E_MapElementType.Corridor, corridorStartX, corridorStartZ); currentCorridorScript.startX = corridorStartX; currentCorridorScript.startZ = corridorStartZ; currentCorridorScript.dirX = corridorDirDeltaX; currentCorridorScript.dirZ = corridorDirDeltaZ; //generate tiles currentCorridorScript.tileSingle = new Transform[corridorLength]; currentCorridorScript.walls = new List <Transform> (); for (int i = 0; i < corridorLength; i++) { currentCorridorScript.tileSingle[i] = RandomlyCreateTile(corridorDirDeltaX * i, corridorDirDeltaZ * i, floorTiles); if (corridorDirDeltaX == 0) { layerTile[corridorStartX, corridorStartZ + corridorDirDeltaZ * i] = E_TileType.corridor_Vertical; RandomlyCreateWall(corridorDirDeltaX * i, corridorDirDeltaZ * i, wallTiles, E_Direction.Left, currentCorridorScript.walls); RandomlyCreateWall(corridorDirDeltaX * i, corridorDirDeltaZ * i, wallTiles, E_Direction.Right, currentCorridorScript.walls); } else { layerTile[corridorStartX + corridorDirDeltaX * i, corridorStartZ] = E_TileType.corridor_Horizontal; RandomlyCreateWall(corridorDirDeltaX * i, corridorDirDeltaZ * i, wallTiles, E_Direction.Up, currentCorridorScript.walls); RandomlyCreateWall(corridorDirDeltaX * i, corridorDirDeltaZ * i, wallTiles, E_Direction.Down, currentCorridorScript.walls); } //corridor end wall if (i == corridorLength - 1) { RandomlyCreateWall(corridorDirDeltaX * i, corridorDirDeltaZ * i, wallTiles, corridorDir, currentCorridorScript.walls); } } //corridor is created with a exit (beginning) currentCorridorScript.exitCount = 1; return(true); }
//generate a room from a wall on its dir bool CreateRoomFromMapElement(Transform mapElem, E_RoomType roomType, E_TileMaterialType tileMaterialType, int index = -1) { List <Transform> chosenWalls = mapElem.GetComponent <MapElement> ().walls; Transform testedWall; if (index == -1) { testedWall = chosenWalls[Random.Range(0, chosenWalls.Count - 1)]; } else { testedWall = chosenWalls[index]; } int wallX = Mathf.RoundToInt(testedWall.position.x) / tileWidth; int wallZ = Mathf.RoundToInt(testedWall.position.z) / tileWidth; int deltaX, deltaZ; E_Direction WallDir = CheckWallDirection(testedWall); //corridor direction if (WallDir == E_Direction.Unset) { return(false); } switch (WallDir) { case E_Direction.Up: deltaX = 0; deltaZ = 1; break; case E_Direction.Down: deltaX = 0; deltaZ = -1; break; case E_Direction.Left: deltaX = -1; deltaZ = 0; break; case E_Direction.Right: deltaX = 1; deltaZ = 0; break; default: deltaX = 0; deltaZ = 0; return(false); } int roomWidth = Random.Range(minRoomWidth, maxRoomWidth); int roomLength = Random.Range(minRoomLength, maxRoomLength); int roomStartX, roomStartZ, doorDistance; //calculate room startpos and doorpos 根据门离两边的距离算出房间的起始位置 if (deltaX == 0) { doorDistance = Random.Range(1, roomWidth - 2); //避开房间拐角 roomStartX = wallX - doorDistance; if (deltaZ == 1) { roomStartZ = wallZ + deltaZ; } else { roomStartZ = wallZ + deltaZ * roomLength; } } else { doorDistance = Random.Range(1, roomLength - 2); roomStartZ = wallZ - doorDistance; if (deltaX == 1) { roomStartX = wallX + deltaX; } else { roomStartX = wallX + deltaX * roomWidth; } } //calculate a small entrance corridor space and offset roompos //random corridor length int corridorEntranceLength = Random.Range(1, 7); int corridorStartX = wallX + deltaX; int corridorStartZ = wallZ + deltaZ; //offset room roomStartX += deltaX * corridorEntranceLength; roomStartZ += deltaZ * corridorEntranceLength; //material type Transform[] floorTiles, wallTiles; SetTileMaterial(tileMaterialType, out floorTiles, out wallTiles); //create room entrance corridor if (CreateCorridor(corridorStartX, corridorStartZ, corridorEntranceLength, WallDir, tileMaterialType)) { layerCorridors[layerCorridors.Count - 1].GetComponent <MapElement>().removedWall = RemoveWallFromMapElement(wallX + deltaX * corridorEntranceLength, wallZ + deltaZ * corridorEntranceLength, deltaX, deltaZ, layerCorridors[layerCorridors.Count - 1].GetComponent <MapElement>()); } else { return(false); } //为了使房间能顺利建立将入口处layerTile临时替换为empty E_TileType tmpTileType = layerTile [wallX + deltaX * corridorEntranceLength, wallZ + deltaZ * corridorEntranceLength]; layerTile [wallX + deltaX * corridorEntranceLength, wallZ + deltaZ * corridorEntranceLength] = E_TileType.empty; //create room if (CreateRoom(roomStartX, roomStartZ, roomWidth, roomLength, roomType, tileMaterialType)) { RemoveWallFromMapElement(wallX + deltaX * (corridorEntranceLength + 1), wallZ + deltaZ * (corridorEntranceLength + 1), -deltaX, -deltaZ, layerRooms[layerRooms.Count - 1].GetComponent <MapElement>()); } else { GameObject recentCorridorGO = layerCorridors[layerCorridors.Count - 1].gameObject; CancelRecentMapElement(E_MapElementType.Corridor, recentCorridorGO); return(false); } //入口处恢复 layerTile [wallX + deltaX * corridorEntranceLength, wallZ + deltaZ * corridorEntranceLength] = tmpTileType; mapElem.GetComponent <MapElement>().exitCount++; chosenWalls.Remove(testedWall); Destroy(testedWall.gameObject); return(true); }