void GenerateBuildingRooms(ArrayGrid <MapElement> map, Vector2Int buildingPos, Vector2Int roomSize) { Rect building = new Rect(); Rect smaller = new Rect(); buildingPos.x++; buildingPos.y++; building.position = buildingPos; building.size = roomSize; smaller = building; smaller.min = smaller.min + Vector2Int.one; smaller.max = smaller.max - Vector2Int.one; map.FillArea(building, defaultBuildingWallElement); map.FillArea(smaller, defaultRoomElement); AddRecursiveRooms(map, defaultBuildingWallElement, new Vector2Int(innerBuildingRoomSize, innerBuildingRoomSize), smaller); // add a door leading out (improve to lead to nearest road) if (GameRNG.CoinToss()) { if (GameRNG.CoinToss()) { int x = (int)building.min.x + GameRNG.Rand((int)roomSize.x - 2) + 1; int y = (int)building.min.y; map[x, y] = defaultDoorElement; } else { int x = (int)building.min.x + GameRNG.Rand((int)roomSize.x - 2) + 1; int y = (int)building.max.y - 1; map[x, y] = defaultDoorElement; } } else { if (GameRNG.CoinToss()) { int x = (int)building.min.x; int y = (int)building.min.y + GameRNG.Rand((int)roomSize.y - 2) + 1; map[x, y] = defaultDoorElement; } else { int x = (int)building.max.x - 1; int y = (int)building.min.y + GameRNG.Rand((int)roomSize.y - 2) + 1; map[x, y] = defaultDoorElement; } } }
IEnumerator On() { float time = GameRNG.Rand(onTimeMin, onTimeMax); yield return(new WaitForSeconds(time)); bodyCollider.enabled = true; currentState = Off(); yield break; }
IEnumerator Off() { float time = GameRNG.Rand(offTimeMin, offTimeMax); yield return(new WaitForSeconds(time)); ObjectIsInRange = false; bodyCollider.enabled = false; currentState = On(); yield break; }
IEnumerator GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { Vector2Int p1 = Vector2Int.zero; Vector2Int p2 = Vector2Int.zero; Vector2Int r = Vector2Int.zero; List <Rect> rooms = new List <Rect>(); List <int> roomTypes = new List <int>(); int numberOfRooms = 0; for (numberOfRooms = 0; numberOfRooms < maxNumberOfRooms;) { if (numberOfRooms == 0) { p1.x = map.w / 2 - GameRNG.Rand((int)roomSizeLimit.Max); p1.y = map.h / 2 - GameRNG.Rand((int)roomSizeLimit.Max) - (int)roomSizeLimit.Min; r.x = GameRNG.Rand((int)roomSizeLimit.Min, (int)roomSizeLimit.Min + (int)roomSizeLimit.Max); r.y = roomSizeLimit.RandomValuei(); p2.x = p1.x + r.x; p2.y = map.h / 2; if (p2.x >= map.w) { continue; } } else { p1.x = GameRNG.Rand(map.w - (int)roomSizeLimit.Min) + 1; p1.y = GameRNG.Rand(map.h - (int)roomSizeLimit.Min) / 2 + 1; r.x = roomSizeLimit.RandomValuei(); r.y = roomSizeLimit.RandomValuei(); p2.x = p1.x + r.x; p2.y = p1.y + r.y; if (p2.x >= map.w - 1 || p2.y >= map.h / 2 + 3) { continue; } } bool randAgain = false; for (int j = 0; j < rooms.Count; ++j) { randAgain = true; if (rooms[j].Contains(p1)) { if (!rooms[j].Contains(p2)) { randAgain = false; roomTypes[j]++; } break; } if (rooms[j].Contains(p2)) { if (!rooms[j].Contains(p1)) { randAgain = false; roomTypes[j]++; } break; } } if (randAgain) { continue; } // Create room Rect roomRect = Rect.MinMaxRect(p1.x, p1.y, p2.x, p2.y); rooms.Add(roomRect); roomTypes.Add(0); numberOfRooms++; } yield return(new WaitForEndOfFrame()); // create mirror for (int i = 0; i < numberOfRooms; ++i) { Rect roomRect = rooms[i]; if (mirrorVertical) { Vector2Int min = Vector2Int.FloorToInt(roomRect.min); Vector2Int max = Vector2Int.FloorToInt(roomRect.max); min.x = map.w - min.x - 1; max.x = map.w - max.x - 1; p1.x = min.x; min.x = max.x; max.x = p1.x; roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y); } else { Vector2Int min = Vector2Int.FloorToInt(roomRect.min); Vector2Int max = Vector2Int.FloorToInt(roomRect.max); min.y = map.h - min.y - 1; max.y = map.h - max.y - 1; p1.y = min.y; min.y = max.y; max.y = p1.y; roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y); } roomTypes.Insert(i, roomTypes[i]); rooms.Insert(i, roomRect); } yield return(new WaitForEndOfFrame()); for (int i = 0; i < rooms.Count; ++i) { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(Vector2Int.FloorToInt(rooms[i].min), Vector2Int.FloorToInt(rooms[i].max)); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (valueMap[current] == valueWall) { valueMap[current] = roomTypes[i]; } } } yield return(new WaitForEndOfFrame()); int freeCells = 0; for (int x = 0; x < map.MaxValidPosition.x; ++x) { for (int y = 0; y < map.h / 2; ++y) { int currentValue = valueMap[x, y]; int[] nearValues = new int[] { valueMap[x + 1, y] , valueMap[x, y + 1] , valueMap[x + 1, y + 1] }; if (currentValue != nearValues[0] && nearValues[0] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != nearValues[1] && nearValues[1] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != nearValues[2] && nearValues[2] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != valueWall) { freeCells += 2;// +2 for mirror } valueMap[x, map.h - y - 1] = valueMap[x, y];//mirroring } } if (freeCells < (map.h * map.w * requiredPercentageOfMapNotWalls)) { if (debugOutput) { Dev.Log(string.Format("Not enough open map space. {0} < {1}", freeCells, (map.h * map.w * requiredPercentageOfMapNotWalls))); } success = false; yield break; } ConvertValuesToTiles(map, valueMap); ConnectClosestRooms(map, valueMap, true); ConvertValuesToTiles(map, valueMap); AddDoors(map, valueMap, 1f); success = true; yield break; }
protected void ConnectClosestRooms(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap, bool withDoors, bool straightConnections = false) { int roomCount = 0; FillDisconnectedRoomsWithDifferentValues(map, valueMap, ref roomCount); List <List <Vector2Int> > rooms = (new List <Vector2Int> [roomCount]).ToList(); for (int i = 0; i < rooms.Count; ++i) { rooms[i] = new List <Vector2Int>(); } IEnumerator <Vector2Int> mapIter = IterateOverMap(map); while (mapIter.MoveNext()) { Vector2Int current = mapIter.Current; if (valueMap[current] != valueWall) { if (valueMap.GetAdjacentElementsOfType(current, false, valueWall).Count > 0) { int roomIndex = valueMap[current] - 1; rooms[roomIndex].Add(current); } } } if (rooms.Count < 2) { return; } // for warshall algorithm // set the connection matrix GameRNG.RandomShuffle(rooms); List <List <bool> > roomConnections = (new List <bool> [rooms.Count]).ToList(); List <List <bool> > transitiveClosure = (new List <bool> [rooms.Count]).ToList();; List <List <int> > distanceMatrix = (new List <int> [rooms.Count]).ToList(); List <List <KeyValuePair <Vector2Int, Vector2Int> > > closestCellsMatrix = (new List <KeyValuePair <Vector2Int, Vector2Int> > [rooms.Count]).ToList(); for (int a = 0; a < rooms.Count; ++a) { roomConnections[a] = (new bool[rooms.Count]).ToList(); transitiveClosure[a] = (new bool[rooms.Count]).ToList(); distanceMatrix[a] = (new int[rooms.Count]).ToList(); closestCellsMatrix[a] = (new KeyValuePair <Vector2Int, Vector2Int> [rooms.Count]).ToList(); for (int b = 0; b < rooms.Count; ++b) { roomConnections[a][b] = false; distanceMatrix[a][b] = int.MaxValue; } } IEnumerator <Vector2Int> roomAreas = IterateOverArea(rooms.Count, rooms.Count); // find the closest cells for each room - Random closest cell while (roomAreas.MoveNext()) { Vector2Int ci = roomAreas.Current; if (ci.x == ci.y) { continue; } KeyValuePair <Vector2Int, Vector2Int> closestCells = new KeyValuePair <Vector2Int, Vector2Int>(); foreach (Vector2Int cellA in rooms[ci.y]) { foreach (Vector2Int cellB in rooms[ci.x]) { int distAB = Mathf.CeilToInt((cellA - cellB).magnitude); if ((distAB < distanceMatrix[ci.y][ci.x]) || (distAB == distanceMatrix[ci.y][ci.x] && GameRNG.CoinToss())) { closestCells = new KeyValuePair <Vector2Int, Vector2Int>(cellA, cellB); distanceMatrix[ci.y][ci.x] = distAB; } } } closestCellsMatrix[ci.y][ci.x] = closestCells; } // Now connect the rooms to the closest ones for (int roomA = 0; roomA < rooms.Count; ++roomA) { int minDist = int.MaxValue; int closestRoom = 0; for (int roomB = 0; roomB < rooms.Count; ++roomB) { if (roomA == roomB) { continue; } int distance = distanceMatrix[roomA][roomB]; if (distance < minDist) { minDist = distance; closestRoom = roomB; } } // connect roomA to closest one KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[roomA][closestRoom]; if (!roomConnections[roomA][closestRoom] && AddCorridor(map, valueMap, closestCells, straightConnections)) { roomConnections[roomA][closestRoom] = true; roomConnections[closestRoom][roomA] = true; } } // The closest rooms connected. Connect the rest until all areas are connected for (int toConnectA = 0; toConnectA != -1;) { roomAreas = IterateOverArea(rooms.Count, rooms.Count); while (roomAreas.MoveNext()) { Vector2Int ci = roomAreas.Current; transitiveClosure[ci.y][ci.x] = roomConnections[ci.y][ci.x]; } roomAreas = IterateOverArea(rooms.Count, rooms.Count); while (roomAreas.MoveNext()) { Vector2Int ci = roomAreas.Current; if (transitiveClosure[ci.y][ci.x] == true && ci.y != ci.x) { for (int ciZ = 0; ciZ < rooms.Count; ++ciZ) { if (transitiveClosure[ci.x][ciZ] == true) { transitiveClosure[ci.y][ciZ] = true; transitiveClosure[ciZ][ci.y] = true; } } } } toConnectA = -1; roomAreas = IterateOverArea(rooms.Count, rooms.Count); while (roomAreas.MoveNext() && toConnectA == -1) { Vector2Int ci = roomAreas.Current; if (transitiveClosure[ci.y][ci.x] == false && ci.x != ci.y) { toConnectA = ci.y; break; } } if (toConnectA != -1) { int toConnectB = toConnectA; while (toConnectB == toConnectA) { toConnectB = GameRNG.Rand(rooms.Count); } KeyValuePair <Vector2Int, Vector2Int> closestCells = closestCellsMatrix[toConnectA][toConnectB]; AddCorridor(map, valueMap, closestCells, straightConnections); { roomConnections[toConnectA][toConnectB] = true; roomConnections[toConnectB][toConnectA] = true; } } } }
public float RandomNormalizedValue() { return(NormalizedValue(GameRNG.Rand(Min, Max))); }
public float RandomValuef() { return(GameRNG.Rand(Min, Max)); }
public int RandomValuei() { return(GameRNG.Rand((int)Min, (int)Max)); }
bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { List <Vector2Int> drillers = new List <Vector2Int>(); drillers.Add(new Vector2Int(map.w / 2, map.h / 2)); while (drillers.Count > 0) { int i = 0; while (i < drillers.Count) { Vector2Int di = drillers[i]; bool removeDriller = false; int behavior = GameRNG.Rand(4); if (behavior == 0) { di.y -= 2; if (di.y < 0 || map[di] == defaultCorridorElement) { removeDriller = (!allowLoops || (allowLoops && GameRNG.Randf() < loopProb)); } if (!removeDriller) { map[di.x, di.y + 1] = defaultCorridorElement; } } else if (behavior == 1) { di.y += 2; if (di.y >= map.h || map[di] == defaultCorridorElement) { removeDriller = true; } else { map[di.x, di.y - 1] = defaultCorridorElement; } } else if (behavior == 2) { di.x -= 2; if (di.x < 0 || map[di] == defaultCorridorElement) { removeDriller = true; } else { map[di.x + 1, di.y] = defaultCorridorElement; } } else if (behavior == 3) { di.x += 2; if (di.x >= map.w || map[di] == defaultCorridorElement) { removeDriller = true; } else { map[di.x - 1, di.y] = defaultCorridorElement; } } if (removeDriller) { drillers.RemoveAt(i); } else { drillers[i] = di; drillers.Add(di); drillers.Add(di); map[di] = defaultCorridorElement; ++i; } } } return(true); }
bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { Vector2Int s0 = Vector2Int.zero; Vector2Int s1 = Vector2Int.zero; Vector2Int p0 = Vector2Int.zero; Vector2Int p1 = Vector2Int.zero; Vector2Int p2 = Vector2Int.zero; Vector2Int diff = Vector2Int.zero; List <Rect> rooms = new List <Rect>(); List <int> roomTypes = new List <int>(); // Place rooms for (int i = 0; i < maxNumberOfRooms; ++i) { // size of room s1 = new Vector2Int(roomSizeLimitX.RandomValuei(), roomSizeLimitY.RandomValuei()); bool result = map.GetPositionOfRandomAreaOfType(defaultWallElement, s1 + roomSizeOffset, ref p0); if (result) { p0 = p0.AddScalar(2); // Connect the room to existing one if (rooms.Count > 0) { int selectedRoom = GameRNG.Rand(rooms.Count); Rect r = rooms[selectedRoom]; // center of this room p1 = p0 + s1.DivideBy(2); // center of second room p2 = Vector2Int.FloorToInt(r.center); // found the way to connect rooms diff = p2 - p1; diff.x = Mathf.Abs(diff.x); diff.y = Mathf.Abs(diff.y); s0 = p1; while (!(diff.x == 0 && diff.y == 0)) { if (GameRNG.Rand(diff.x + diff.y) < diff.x)// move horizontally { diff.x--; s0.x += (s0.x > p2.x ? -1 : 1); } else { diff.y--; s0.y += (s0.y > p2.y ? -1 : 1); } // Check what is on that position if (map[s0] == defaultRoomElement) { break; } else if (map[s0] == defaultCorridorElement) { if (GameRNG.CoinToss()) { break; } } map[s0] = defaultCorridorElement; } } // add to list of rooms Rect roomRect = Rect.MinMaxRect(p0.x, p0.y, p0.x + s1.x, p0.y + s1.y); rooms.Add(roomRect); roomTypes.Add(i); // draw_room int roomType = GameRNG.Rand(4); //select the type of room we should generate if (s1.x == s1.y) { roomType = 3; } if (roomType != 2) { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (roomType == 0 || roomType == 1)// rectangle room { map[p0 + current] = defaultRoomElement; } else// round room { if (Vector2Int.Distance(s1.DivideBy(2), current) < s1.x / 2) { map[p0 + current] = defaultRoomElement; } } } } else //diamond { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1.DivideBy(2) + Vector2Int.one); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (current.y >= current.x) { int x0 = p0.x + current.x + s1.DivideBy(2).x; int x1 = p0.x + s1.DivideBy(2).x - current.x; int y0 = p0.y + current.y; int y1 = p0.y + s1.y - current.y; map[x0, y0] = defaultRoomElement; map[x0, y1] = defaultRoomElement; map[x1, y0] = defaultRoomElement; map[x1, y1] = defaultRoomElement; } } } } // end of room addition } return(true); }
void AddRecursiveRooms(ArrayGrid <MapElement> map, MapElement roomElement, Vector2Int minRoomSize, Rect room, bool withDoors = true) { int sizeX = (int)room.size.x; if (sizeX % 2 != 0) { sizeX -= GameRNG.CoinToss() ? 1 : 0; } int sizeY = (int)room.size.y; if (sizeY % 2 != 0) { sizeY -= GameRNG.CoinToss() ? 1 : 0; } bool splitHorizontal = false; if (sizeY * 4 > sizeX) { splitHorizontal = true; } if (sizeX * 4 > sizeY) { splitHorizontal = false; } else { splitHorizontal = GameRNG.CoinToss(); } if (splitHorizontal) { if (sizeY / 2 < minRoomSize.y) { return; } int split = sizeY / 2 + GameRNG.Rand(sizeY / 2 - (int)minRoomSize.y); for (int x = (int)room.min.x; x < (int)room.max.x; ++x) { map[x, (int)room.min.y + split] = roomElement; } if (withDoors) { map[(int)room.min.x + GameRNG.Rand(sizeX - 1) + 1, (int)room.min.y + split] = defaultDoorElement; } Rect newRoom = room; Vector2Int newMax = newRoom.max.ToInt(); newMax.y = room.min.ToInt().y + split; newRoom.max = newMax; AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors); newRoom = room; Vector2Int newMin = newRoom.min.ToInt(); newMin.y = room.min.ToInt().y + split; newRoom.min = newMin; AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors); } else { if (sizeX / 2 < minRoomSize.x) { return; } int split = sizeX / 2 + GameRNG.Rand(sizeX / 2 - (int)minRoomSize.x); for (int y = (int)room.min.y; y < (int)room.max.y; ++y) { map[(int)room.min.x + split, y] = roomElement; } if (withDoors) { map[(int)room.min.x + split, (int)room.min.y + GameRNG.Rand(sizeY - 1) + 1] = defaultDoorElement; } Rect newRoom = room; Vector2Int newMax = newRoom.max.ToInt(); newMax.x = room.min.ToInt().x + split; newRoom.max = newMax; AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors); newRoom = room; Vector2Int newMin = newRoom.min.ToInt(); newMin.x = room.min.ToInt().x + split; newRoom.min = newMin; AddRecursiveRooms(map, roomElement, minRoomSize, newRoom, withDoors); } }