Implemented generation of normal rooms around monster rooms. They still collid with each other.
This commit is contained in:
parent
2cd9df5652
commit
e0c65bd66e
3 changed files with 256 additions and 6 deletions
|
|
@ -11,7 +11,8 @@ namespace DungeonGenerator
|
|||
public class DungeonGenerator
|
||||
{
|
||||
private const int SIDE_LENGTH_OF_MONSTER = 4;
|
||||
private const int SIDE_LENGTH_OF_NORMAL = 2;
|
||||
private const int SIDE_LENGTH_OF_NORMAL = 2;
|
||||
private const int SIDE_LENGTH_OF_ENTRANCE = 2;
|
||||
private const int WIDTH_OF_BOSS = 10;
|
||||
private const int HEIGHT_OF_BOSS = 6;
|
||||
|
||||
|
|
@ -40,10 +41,192 @@ namespace DungeonGenerator
|
|||
RoomType.Monster));
|
||||
}
|
||||
|
||||
|
||||
AddNormalRoomsAroundMonsterRooms(dungeonMap);
|
||||
|
||||
return dungeonMap;
|
||||
}
|
||||
|
||||
enum RoomSide
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
private void AddNormalRoomsAroundMonsterRooms(DungeonMap dungeon)
|
||||
{
|
||||
HashSet<Point> unoccupiedPoints = dungeon.GetUnoccupiedPoints();
|
||||
Random random = new Random();
|
||||
foreach (Room monsterRoom in dungeon.GetMonsterRooms())
|
||||
{
|
||||
var roomPoints = monsterRoom.GetPointsInRoom();
|
||||
int minX = roomPoints.Min(p => p.X);
|
||||
int maxX = roomPoints.Max(p => p.X);
|
||||
int minY = roomPoints.Min(p => p.Y);
|
||||
int maxY = roomPoints.Max(p => p.Y);
|
||||
|
||||
List<Point> topUnoccupiedPoints = new List<Point>();
|
||||
List<Point> bottomUnoccupiedPoints = new List<Point>();
|
||||
List<Point> leftUnoccupiedPoints = new List<Point>();
|
||||
List<Point> rightUnoccupiedPoints = new List<Point>();
|
||||
|
||||
for (int x = minX - SIDE_LENGTH_OF_NORMAL; x <= maxX + SIDE_LENGTH_OF_NORMAL; x++)
|
||||
{
|
||||
Point point = new Point(x, minY - SIDE_LENGTH_OF_NORMAL);
|
||||
if (unoccupiedPoints.Contains(point))
|
||||
{
|
||||
topUnoccupiedPoints.Add(point);
|
||||
}
|
||||
|
||||
point = new Point(x, maxY + SIDE_LENGTH_OF_NORMAL);
|
||||
if (unoccupiedPoints.Contains(point))
|
||||
{
|
||||
bottomUnoccupiedPoints.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = minY - SIDE_LENGTH_OF_NORMAL; y <= maxY + SIDE_LENGTH_OF_NORMAL; y++)
|
||||
{
|
||||
Point point = new Point(minX - SIDE_LENGTH_OF_NORMAL, y);
|
||||
if (unoccupiedPoints.Contains(point))
|
||||
{
|
||||
leftUnoccupiedPoints.Add(point);
|
||||
}
|
||||
|
||||
point = new Point(maxX + SIDE_LENGTH_OF_NORMAL, y);
|
||||
if (unoccupiedPoints.Contains(point))
|
||||
{
|
||||
rightUnoccupiedPoints.Add(point);
|
||||
}
|
||||
}
|
||||
|
||||
int minNecessaryAvailablePoints = (SIDE_LENGTH_OF_MONSTER + SIDE_LENGTH_OF_NORMAL) / 2;
|
||||
|
||||
List<RoomSide> availableSides = new List<RoomSide>();
|
||||
if (topUnoccupiedPoints.Count >= minNecessaryAvailablePoints){availableSides.Add(RoomSide.Top);}
|
||||
if (bottomUnoccupiedPoints.Count >= minNecessaryAvailablePoints){availableSides.Add(RoomSide.Bottom);}
|
||||
if (leftUnoccupiedPoints.Count >= minNecessaryAvailablePoints){availableSides.Add(RoomSide.Left);}
|
||||
if (rightUnoccupiedPoints.Count >= minNecessaryAvailablePoints){availableSides.Add(RoomSide.Right);}
|
||||
|
||||
// Ensure between 3 and 4 rooms are added
|
||||
int numRoomsToAdd = Math.Min(availableSides.Count, random.Next(3, 5));
|
||||
|
||||
// Randomly shuffle and take the required number of sides
|
||||
List<Room> newRooms = new List<Room>();
|
||||
foreach (RoomSide side in availableSides.OrderBy(_ => random.Next()).Take(numRoomsToAdd))
|
||||
{
|
||||
// Select appropriate unoccupied points based on the side
|
||||
List<Point> unoccupiedPointsOnSide = side switch
|
||||
{
|
||||
RoomSide.Top => topUnoccupiedPoints,
|
||||
RoomSide.Bottom => bottomUnoccupiedPoints,
|
||||
RoomSide.Left => leftUnoccupiedPoints,
|
||||
RoomSide.Right => rightUnoccupiedPoints,
|
||||
_ => new List<Point>()
|
||||
};
|
||||
|
||||
// Create room and add it if valid
|
||||
Room newRoom = CreateAdjacentRoom(RoomType.Normal, unoccupiedPointsOnSide, side);
|
||||
if (newRoom != null)
|
||||
{
|
||||
newRooms.Add(newRoom);
|
||||
}
|
||||
}
|
||||
dungeon.AddRooms(newRooms);
|
||||
}
|
||||
}
|
||||
|
||||
private Room CreateAdjacentRoom(RoomType type, List<Point> unoccupiedPointsOnSide, RoomSide side)
|
||||
{
|
||||
int sizeOfNewRoom = GetRoomSizeByType(type);
|
||||
Random random = new Random();
|
||||
|
||||
// Sort points by their coordinate based on the side of placement
|
||||
var orderedPoints = side == RoomSide.Left || side == RoomSide.Right
|
||||
? unoccupiedPointsOnSide.OrderBy(p => p.Y).ToList() // Sort by Y for vertical placement
|
||||
: unoccupiedPointsOnSide.OrderBy(p => p.X).ToList();
|
||||
|
||||
// List to store possible valid room placements (top-left points of the room)
|
||||
List<Point> validPlacements = new List<Point>();
|
||||
|
||||
// Iterate over the ordered points to find potential placements
|
||||
for (int i = 0; i < orderedPoints.Count - sizeOfNewRoom + 1; i++)
|
||||
{
|
||||
// Get a sequence of SIZE_OF_ROOM points starting from index i
|
||||
var potentialPoints = orderedPoints.Skip(i).Take(sizeOfNewRoom).ToList();
|
||||
|
||||
// Check if all points are consecutive and fit within the range
|
||||
if (IsRoomWideEnough(potentialPoints, side))
|
||||
{
|
||||
Point firstPoint = potentialPoints.First();
|
||||
|
||||
// Adjust the first point for different sides
|
||||
Point adjustedPoint = side switch
|
||||
{
|
||||
RoomSide.Top => new Point(firstPoint.X, firstPoint.Y), // Move up for top side
|
||||
RoomSide.Bottom => new Point(firstPoint.X, firstPoint.Y - 1), // Move down for bottom side
|
||||
RoomSide.Left => new Point(firstPoint.X, firstPoint.Y), // Move left for left side
|
||||
RoomSide.Right => new Point(firstPoint.X - 1, firstPoint.Y), // Move right for right side
|
||||
_ => firstPoint // Default case (shouldn't happen)
|
||||
};
|
||||
|
||||
// If the points are wide enough, store the top-left point for the room
|
||||
validPlacements.Add(adjustedPoint); // First point is the top-left point of the room
|
||||
}
|
||||
}
|
||||
|
||||
// If there are valid placements, select a random one and create the room
|
||||
if (validPlacements.Any())
|
||||
{
|
||||
Point randomPlacement = validPlacements[random.Next(validPlacements.Count)];
|
||||
return new Room(type, sizeOfNewRoom, sizeOfNewRoom, randomPlacement);
|
||||
}
|
||||
|
||||
// If no valid placements are found, return null or handle it as necessary
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper method to check if a sequence of points is wide enough (consecutive points)
|
||||
private bool IsRoomWideEnough(List<Point> points, RoomSide side)
|
||||
{
|
||||
for (int i = 1; i < points.Count; i++)
|
||||
{
|
||||
if (side == RoomSide.Left || side == RoomSide.Right)
|
||||
{
|
||||
// Check if points are consecutive along the Y-axis for left/right side
|
||||
if (points[i].Y != points[i - 1].Y + 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if points are consecutive along the X-axis for top/bottom side
|
||||
if (points[i].X != points[i - 1].X + 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int GetRoomSizeByType(RoomType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RoomType.Entrance:
|
||||
return SIDE_LENGTH_OF_ENTRANCE;
|
||||
case RoomType.Monster:
|
||||
return
|
||||
SIDE_LENGTH_OF_MONSTER;
|
||||
case RoomType.Normal:
|
||||
return SIDE_LENGTH_OF_NORMAL;
|
||||
default:
|
||||
return SIDE_LENGTH_OF_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
private Room GenerateOnlyBossRoom(int xLengthOfDungeon, int yLengthOfDungeon, int width, int heigth)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace DungeonGenerator
|
|||
private int _height;
|
||||
private List<Room> _monsterRooms = new List<Room>();
|
||||
private List<Room> _entranceRooms = new List<Room>();
|
||||
private List<Room> _normalRooms = new List<Room>();
|
||||
private Room _bossRoom;
|
||||
private HashSet<Point> _unoccupiedPoints = new HashSet<Point>();
|
||||
|
||||
|
|
@ -35,6 +36,9 @@ namespace DungeonGenerator
|
|||
case RoomType.Entrance:
|
||||
_entranceRooms.Add(room);
|
||||
break;
|
||||
case RoomType.Normal:
|
||||
_normalRooms.Add(room);
|
||||
break;
|
||||
case RoomType.Boss:
|
||||
_bossRoom = room;
|
||||
break;
|
||||
|
|
@ -47,6 +51,8 @@ namespace DungeonGenerator
|
|||
|
||||
public void AddRooms(List<Room> rooms)
|
||||
{
|
||||
if (rooms.Count == 0) return;
|
||||
|
||||
switch (rooms[0].TypeOfRoom)
|
||||
{
|
||||
case RoomType.Monster:
|
||||
|
|
@ -55,6 +61,9 @@ namespace DungeonGenerator
|
|||
case RoomType.Entrance:
|
||||
_entranceRooms.AddRange(rooms);
|
||||
break;
|
||||
case RoomType.Normal:
|
||||
_normalRooms.AddRange(rooms);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
@ -77,6 +86,11 @@ namespace DungeonGenerator
|
|||
return _entranceRooms;
|
||||
}
|
||||
|
||||
public List<Room> GetNormalRooms()
|
||||
{
|
||||
return _normalRooms;
|
||||
}
|
||||
|
||||
public HashSet<Point> GetUnoccupiedPoints()
|
||||
{
|
||||
return new HashSet<Point>(_unoccupiedPoints);
|
||||
|
|
@ -86,23 +100,29 @@ namespace DungeonGenerator
|
|||
{
|
||||
List<Point> monsterRoomPoints = _monsterRooms.SelectMany(room => room.GetPointsInRoom()).ToList();
|
||||
List<Point> entranceRoomPoints = _entranceRooms.SelectMany(room => room.GetPointsInRoom()).ToList();
|
||||
List<Point> normalRoomPoints = _normalRooms.SelectMany(room => room.GetPointsInRoom()).ToList();
|
||||
char[,] mapMatrix = new Char[_width, _height];
|
||||
for (int x = 0; x < _width; x++)
|
||||
{
|
||||
for (int y = 0; y < _height; y++)
|
||||
{
|
||||
if (entranceRoomPoints.Contains(new Point(x, y)))
|
||||
Point point = new Point(x, y);
|
||||
if (entranceRoomPoints.Contains(point))
|
||||
{
|
||||
mapMatrix[x, y] = '*';
|
||||
}
|
||||
else if (monsterRoomPoints.Contains(new Point(x,y)))
|
||||
else if (monsterRoomPoints.Contains(point))
|
||||
{
|
||||
mapMatrix[x, y] = 'X';
|
||||
}
|
||||
else if (_bossRoom.GetPointsInRoom().Contains(new Point(x, y)))
|
||||
else if (_bossRoom.GetPointsInRoom().Contains(point))
|
||||
{
|
||||
mapMatrix[x, y] = 'B';
|
||||
}
|
||||
else if (normalRoomPoints.Contains(point))
|
||||
{
|
||||
mapMatrix[x, y] = 'N';
|
||||
}
|
||||
else
|
||||
{
|
||||
mapMatrix[x, y] = '-';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.VisualScripting;
|
||||
|
||||
namespace DungeonGenerator
|
||||
{
|
||||
|
|
@ -19,7 +21,12 @@ namespace DungeonGenerator
|
|||
Height = height;
|
||||
PositionOfTopLeft = positionOfTopLeft;
|
||||
}
|
||||
|
||||
|
||||
private List<Room> _topAdjacentRooms = new List<Room>();
|
||||
private List<Room> _bottomAdjacentRooms = new List<Room>();
|
||||
private List<Room> _leftAdjacentRooms = new List<Room>();
|
||||
private List<Room> _rightAdjacentRooms = new List<Room>();
|
||||
|
||||
public RoomType TypeOfRoom { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int Width { get; set; }
|
||||
|
|
@ -50,5 +57,45 @@ namespace DungeonGenerator
|
|||
{
|
||||
return new Point(PositionOfTopLeft.X + Width / 2, PositionOfTopLeft.Y + Height / 2);
|
||||
}
|
||||
|
||||
public void AddTopAdjacentRoom(Room room)
|
||||
{
|
||||
_topAdjacentRooms.Add(room);
|
||||
}
|
||||
|
||||
public List<Room> GetTopAdjaceRooms()
|
||||
{
|
||||
return _topAdjacentRooms;
|
||||
}
|
||||
|
||||
public void AddBottomAdjacentRoom(Room room)
|
||||
{
|
||||
_bottomAdjacentRooms.Add(room);
|
||||
}
|
||||
|
||||
public List<Room> GetBottomAdjaceRooms()
|
||||
{
|
||||
return _bottomAdjacentRooms;
|
||||
}
|
||||
|
||||
public void AddLeftAdjacentRoom(Room room)
|
||||
{
|
||||
_leftAdjacentRooms.Add(room);
|
||||
}
|
||||
|
||||
public List<Room> GetLeftAdjaceRooms()
|
||||
{
|
||||
return _leftAdjacentRooms;
|
||||
}
|
||||
|
||||
public void AddRightAdjacentRoom(Room room)
|
||||
{
|
||||
_rightAdjacentRooms.Add(room);
|
||||
}
|
||||
|
||||
public List<Room> GetRightAdjaceRooms()
|
||||
{
|
||||
return _rightAdjacentRooms;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue