Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using Yukar.Engine;
- using System.IO;
- namespace Bakin
- {
- public static class DungeonConstants
- {
- public const int DEFAULT_FLOOR = 1;
- public const int DEFAULT_WALL = 15;
- public const int DEFAULT_CORRIDOR = 1;
- public const int FLOOR_HEIGHT = 0;
- public const int WALL_HEIGHT = 15;
- }
- public class Testing : BakinObject
- {
- private MapScene mapScene;
- private DungeonData currentDungeon;
- private const string SAVE_DIRECTORY = "SavedDungeons";
- private const string FILE_EXTENSION = ".dungeon";
- public override void Start()
- {
- mapScene = GameMain.instance.mapScene;
- if (GameMain.instance.getScenes() == GameMain.Scenes.TITLE ||
- GameMain.instance.getScenes() == GameMain.Scenes.LOADING ||
- mapScene == null)
- return;
- Directory.CreateDirectory(SAVE_DIRECTORY);
- }
- [BakinFunction(Description = "1) Generate basic dungeon (23x23)")]
- public void Generate()
- {
- GenerateNewDungeon(23, 23, 4, 8, 5,
- DungeonConstants.DEFAULT_FLOOR,
- DungeonConstants.DEFAULT_WALL,
- DungeonConstants.DEFAULT_CORRIDOR);
- }
- [BakinFunction(Description = "2) Save current dungeon")]
- public void Save(string dungeonName)
- {
- SaveDungeon(dungeonName);
- }
- [BakinFunction(Description = "3) Load saved dungeon")]
- public void Load(string dungeonName)
- {
- LoadDungeon(dungeonName);
- }
- [BakinFunction(Description = "4) Generate custom size dungeon (width_height)")]
- public void GenerateCustomSize(string size)
- {
- string[] dimensions = size.Split('_');
- if (dimensions.Length == 2 && int.TryParse(dimensions[0], out int width) && int.TryParse(dimensions[1], out int height))
- {
- GenerateNewDungeon(width, height, 3, 6, 100,
- DungeonConstants.DEFAULT_FLOOR,
- DungeonConstants.DEFAULT_WALL,
- DungeonConstants.DEFAULT_CORRIDOR);
- }
- }
- [BakinFunction(Description = "5) Generate with custom terrain (floor_wall_corridor)")]
- public void GenerateCustomTerrain(string terrainTypes)
- {
- string[] types = terrainTypes.Split('_');
- if (types.Length == 3 && int.TryParse(types[0], out int floor) &&
- int.TryParse(types[1], out int wall) && int.TryParse(types[2], out int corridor))
- {
- GenerateNewDungeon(23, 23, 3, 6, 100, floor, wall, corridor);
- }
- }
- [BakinFunction(Description = "0) Clear/Reset current dungeon")]
- public void Clear()
- {
- if (mapScene?.mapDrawer == null) return;
- int width = currentDungeon != null ? currentDungeon.Width : 23;
- int height = currentDungeon != null ? currentDungeon.Height : 23;
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- mapScene.mapDrawer.setTerrain(x, y, 1, 1, true);
- }
- }
- mapScene.mapDrawer.updateMapHeightAndWalkableState(true);
- currentDungeon = null;
- }
- private void GenerateNewDungeon(int width, int height, int minRoomSize, int maxRoomSize, int maxRooms,
- int floorType, int wallType, int corridorType)
- {
- currentDungeon = new DungeonData(width, height)
- {
- FloorType = floorType,
- WallType = wallType,
- CorridorType = corridorType
- };
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- currentDungeon.TerrainData[x, y] = wallType;
- }
- }
- GenerateRooms(minRoomSize, maxRoomSize, maxRooms);
- }
- private void SaveDungeon(string saveName)
- {
- if (currentDungeon == null) return;
- string filePath = Path.Combine(SAVE_DIRECTORY, saveName + FILE_EXTENSION);
- string data = SerializeDungeon(currentDungeon);
- File.WriteAllText(filePath, data);
- }
- private void LoadDungeon(string saveName)
- {
- string filePath = Path.Combine(SAVE_DIRECTORY, saveName + FILE_EXTENSION);
- if (!File.Exists(filePath)) return;
- string data = File.ReadAllText(filePath);
- currentDungeon = DeserializeDungeon(data);
- ApplyDungeonToMap();
- }
- private string SerializeDungeon(DungeonData dungeon)
- {
- List<string> lines = new List<string>
- {
- $"Width:{dungeon.Width}",
- $"Height:{dungeon.Height}",
- $"Floor:{dungeon.FloorType}",
- $"Wall:{dungeon.WallType}",
- $"Corridor:{dungeon.CorridorType}"
- };
- for (int y = 0; y < dungeon.Height; y++)
- {
- string row = "";
- for (int x = 0; x < dungeon.Width; x++)
- {
- row += dungeon.TerrainData[x, y].ToString();
- if (x < dungeon.Width - 1) row += ",";
- }
- lines.Add(row);
- }
- return string.Join("\n", lines);
- }
- private DungeonData DeserializeDungeon(string data)
- {
- string[] lines = data.Split('\n');
- int width = int.Parse(lines[0].Split(':')[1]);
- int height = int.Parse(lines[1].Split(':')[1]);
- DungeonData dungeon = new DungeonData(width, height);
- dungeon.FloorType = int.Parse(lines[2].Split(':')[1]);
- dungeon.WallType = int.Parse(lines[3].Split(':')[1]);
- dungeon.CorridorType = int.Parse(lines[4].Split(':')[1]);
- for (int y = 0; y < height; y++)
- {
- string[] values = lines[y + 5].Split(',');
- for (int x = 0; x < width; x++)
- {
- dungeon.TerrainData[x, y] = int.Parse(values[x]);
- }
- }
- return dungeon;
- }
- private void ApplyDungeonToMap()
- {
- if (mapScene?.mapDrawer == null || currentDungeon == null) return;
- for (int x = 0; x < currentDungeon.Width; x++)
- {
- for (int y = 0; y < currentDungeon.Height; y++)
- {
- bool isWall = currentDungeon.TerrainData[x, y] == currentDungeon.WallType;
- if (isWall)
- {
- mapScene.mapDrawer.setTerrainHeight(x, y, 15);
- mapScene.mapDrawer.setTerrain(x, y, 15, 15, true);
- }
- else
- {
- mapScene.mapDrawer.setTerrainHeight(x, y, 0);
- mapScene.mapDrawer.setTerrain(x, y, 1, 0, true);
- }
- }
- }
- mapScene.mapDrawer.updateMapHeightAndWalkableState(true);
- }
- private void GenerateRooms(int minRoomSize, int maxRoomSize, int maxRooms)
- {
- List<Room> rooms = new List<Room>();
- Random random = new Random();
- int attempts = 0;
- while (rooms.Count < maxRooms && attempts < 1000)
- {
- int roomWidth = random.Next(minRoomSize, maxRoomSize + 1);
- int roomHeight = random.Next(minRoomSize, maxRoomSize + 1);
- int roomX = random.Next(2, currentDungeon.Width - roomWidth - 2);
- int roomY = random.Next(2, currentDungeon.Height - roomHeight - 2);
- Room newRoom = new Room(roomX, roomY, roomWidth, roomHeight);
- bool tooClose = rooms.Exists(r =>
- Math.Abs(r.CenterX - newRoom.CenterX) < roomWidth + 2 ||
- Math.Abs(r.CenterY - newRoom.CenterY) < roomHeight + 2);
- if (!tooClose)
- {
- rooms.Add(newRoom);
- for (int x = roomX - 1; x <= roomX + roomWidth; x++)
- {
- for (int y = roomY - 1; y <= roomY + roomHeight; y++)
- {
- if (x == roomX - 1 || x == roomX + roomWidth ||
- y == roomY - 1 || y == roomY + roomHeight)
- {
- currentDungeon.TerrainData[x, y] = currentDungeon.WallType;
- }
- else
- {
- currentDungeon.TerrainData[x, y] = currentDungeon.FloorType;
- }
- }
- }
- }
- attempts++;
- }
- ConnectRooms(rooms);
- ApplyDungeonToMap();
- }
- private void ConnectRooms(List<Room> rooms)
- {
- for (int i = 1; i < rooms.Count; i++)
- {
- int prevRoomCenterX = Clamp(rooms[i - 1].CenterX, 1, currentDungeon.Width - 2);
- int prevRoomCenterY = Clamp(rooms[i - 1].CenterY, 1, currentDungeon.Height - 2);
- int currRoomCenterX = Clamp(rooms[i].CenterX, 1, currentDungeon.Width - 2);
- int currRoomCenterY = Clamp(rooms[i].CenterY, 1, currentDungeon.Height - 2);
- CreateCorridor(prevRoomCenterX, prevRoomCenterY, currRoomCenterX, currRoomCenterY);
- }
- }
- private void CreateCorridor(int fromX, int fromY, int toX, int toY)
- {
- int currentX = fromX;
- int currentY = fromY;
- bool horizontalFirst = new Random().Next(2) == 0;
- if (horizontalFirst)
- {
- while (currentX != toX)
- {
- currentX += Math.Sign(toX - currentX);
- CreateCorridorTile(currentX, currentY);
- }
- while (currentY != toY)
- {
- currentY += Math.Sign(toY - currentY);
- CreateCorridorTile(currentX, currentY);
- }
- }
- else
- {
- while (currentY != toY)
- {
- currentY += Math.Sign(toY - currentY);
- CreateCorridorTile(currentX, currentY);
- }
- while (currentX != toX)
- {
- currentX += Math.Sign(toX - currentX);
- CreateCorridorTile(currentX, currentY);
- }
- }
- }
- private void CreateCorridorTile(int x, int y)
- {
- if (x > 0 && x < currentDungeon.Width - 1 && y > 0 && y < currentDungeon.Height - 1)
- {
- currentDungeon.TerrainData[x, y] = currentDungeon.CorridorType;
- if (currentDungeon.TerrainData[x - 1, y] == currentDungeon.WallType)
- currentDungeon.TerrainData[x - 1, y] = currentDungeon.WallType;
- if (currentDungeon.TerrainData[x + 1, y] == currentDungeon.WallType)
- currentDungeon.TerrainData[x + 1, y] = currentDungeon.WallType;
- if (currentDungeon.TerrainData[x, y - 1] == currentDungeon.WallType)
- currentDungeon.TerrainData[x, y - 1] = currentDungeon.WallType;
- if (currentDungeon.TerrainData[x, y + 1] == currentDungeon.WallType)
- currentDungeon.TerrainData[x, y + 1] = currentDungeon.WallType;
- }
- }
- private int Clamp(int value, int min, int max)
- {
- return (value < min) ? min : (value > max) ? max : value;
- }
- }
- [Serializable]
- public class DungeonData
- {
- public int Width { get; set; }
- public int Height { get; set; }
- public int[,] TerrainData { get; set; }
- public int FloorType { get; set; }
- public int WallType { get; set; }
- public int CorridorType { get; set; }
- public DungeonData(int width, int height)
- {
- Width = width;
- Height = height;
- TerrainData = new int[width, height];
- FloorType = DungeonConstants.DEFAULT_FLOOR;
- WallType = DungeonConstants.DEFAULT_WALL;
- CorridorType = DungeonConstants.DEFAULT_CORRIDOR;
- }
- }
- public class Room
- {
- public int X, Y, Width, Height;
- public Room(int x, int y, int width, int height)
- {
- X = x;
- Y = y;
- Width = width;
- Height = height;
- }
- public int CenterX => X + Width / 2;
- public int CenterY => Y + Height / 2;
- public bool Intersects(Room other)
- {
- return X <= other.X + other.Width &&
- X + Width >= other.X &&
- Y <= other.Y + other.Height &&
- Y + Height >= other.Y;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement