From 2fb787a744d4f7a37d81233d2913a5ef39122f73 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 28 Aug 2025 00:38:48 -0300 Subject: Comentarios --- scripts/map/DungeonGenerator.cs | 88 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) (limited to 'scripts/map/DungeonGenerator.cs') diff --git a/scripts/map/DungeonGenerator.cs b/scripts/map/DungeonGenerator.cs index ebb7a3d..1da7e16 100644 --- a/scripts/map/DungeonGenerator.cs +++ b/scripts/map/DungeonGenerator.cs @@ -1,26 +1,51 @@ using Godot; +/// +/// A classe dungeonGenerator cria exatamente um andar da masmorra. +/// Ela é chamada quando necessário. +/// public partial class DungeonGenerator : Node { + /// + /// Coleção de todos os inimigos que o gerador tem acesso. + /// private static readonly Godot.Collections.Array enemies = [ GD.Load("res://assets/definitions/actor/Skeleton.tres") ]; + /// + /// Dimensões do mapa a ser criado. + /// [ExportCategory("Dimension")] [Export] private int width = 80; [Export] private int height = 60; + /// + /// Gerador de números aleatórios + /// [ExportCategory("RNG")] private RandomNumberGenerator rng = new(); + /// + /// Qual seed utilizar. + /// [Export] private ulong seed; + /// + /// Se será utilizada a nossa seed ou a seed padrão da classe RandomNumberGenerator. + /// [Export] private bool useSeed = true; + /// + /// Quantas iterações do algoritmo chamar. + /// [Export] private int iterations = 3; + /// + /// Quantidade máxima de inimigos por sala. + /// [ExportCategory("Monster RNG")] [Export] private int maxMonsterPerRoom = 2; @@ -33,6 +58,11 @@ public partial class DungeonGenerator : Node } } + /// + /// Transforma o tile da posição especificada em chão. + /// + /// o mapa + /// posição para colocar o chão. private static void CarveTile(MapData data, Vector2I pos) { Tile tile = data.GetTile(pos); @@ -41,6 +71,11 @@ public partial class DungeonGenerator : Node tile.SetDefinition(MapData.floorDefinition); } + /// + /// Preenche uma área retangular com chão. + /// + /// O mapa + /// Área para preencher com chão private static void CarveRoom(MapData data, Rect2I room) { for (int y = room.Position.Y; y < room.End.Y; y++) @@ -52,25 +87,34 @@ public partial class DungeonGenerator : Node } } + /// + /// Gera um andar da masmorra. + /// Inimigos são colocados conforme configurações. + /// O jogador é colocado na primeira sala gerada. + /// + /// Jogador. + /// O mapa gerado. public MapData GenerateDungeon(Player player) { MapData data = new MapData(width, height, player); - data.InsertActor(player); - player.Map_Data = data; - + // Divisão mestre que engloba o mapa inteiro. MapDivision root = new MapDivision(0, 0, width, height); + // Chama o algoritmo para dividir o mapa. root.Split(iterations, rng); bool first = true; + // Coloca os corredores. TunnelDivisions(data, root); + // Cria as salas com base nas divisões geradas. foreach(MapDivision division in root.GetLeaves()) { Rect2I room = new(division.Position, division.Size); + // A sala não pode oculpar a divisão inteira, senão não haveriam paredes. room = room.GrowIndividual( -rng.RandiRange(1, 2), -rng.RandiRange(1, 2), @@ -78,28 +122,40 @@ public partial class DungeonGenerator : Node -rng.RandiRange(1, 2) ); + // De fato cria a sala. CarveRoom(data, room); + // Colocamos o jogador na primeira sala. if (first) { first = false; player.GridPosition = room.GetCenter(); } + // Colocamos os inimigos na sala. PlaceEntities(data, room); } + // Feito o mapa, inicializamos o algoritmo de pathfinding. data.SetupPathfinding(); return data; } + /// + /// Popula uma sala com inimigos. + /// + /// O mapa + /// A sala. private void PlaceEntities(MapData data, Rect2I room) { + // Define quantos monstros serão colocados na sala int monsterAmount = rng.RandiRange(0, maxMonsterPerRoom); for (int i = 0; i < monsterAmount; i++) { + // Escolhe um lugar aleatório na sala. Vector2I position = new( rng.RandiRange(room.Position.X, room.End.X - 1), rng.RandiRange(room.Position.Y, room.End.Y - 1) ); + // Só podemos colocar um ator por ponto no espaço. bool canPlace = true; foreach (Actor actor in data.Actors) { if (actor.GridPosition == position) { @@ -108,6 +164,7 @@ public partial class DungeonGenerator : Node } } + // Se possível, criamos um inimigo aleatório na posição escolhida. if (canPlace) { EnemyDefinition definition = enemies.PickRandom(); Enemy enemy = new Enemy(position, data, definition); @@ -116,6 +173,13 @@ public partial class DungeonGenerator : Node } } + /// + /// Preenche uma linha horizontal com chão. + /// + /// O mapa + /// Eixo y do corredor. + /// Início do corredor + /// Final do corredor. private static void HorizontalCorridor(MapData data, int y, int xBegin, int xEnd) { int begin = (xBegin < xEnd) ? xBegin : xEnd; int end = (xEnd > xBegin) ? xEnd : xBegin; @@ -124,6 +188,13 @@ public partial class DungeonGenerator : Node } } + /// + /// Preenche uma linha vertical com chão. + /// + /// O mapa. + /// Eixo x do corredor. + /// Início do corredor + /// Final do corredor. private static void VerticalCorridor(MapData data, int x, int yBegin, int yEnd) { int begin = (yBegin < yEnd) ? yBegin : yEnd; int end = (yEnd > yBegin) ? yEnd : yBegin; @@ -132,11 +203,22 @@ public partial class DungeonGenerator : Node } } + /// + /// Cria corredores vertical e horizontal para unir dois pontos no mapa. + /// + /// O mapa + /// Ponto inicial + /// Ponto final. private void TunnelBetween(MapData data, Vector2I start, Vector2I end) { HorizontalCorridor(data, start.Y, start.X, end.X); VerticalCorridor(data, end.X, start.Y, end.Y); } + /// + /// Cria recursivamente corredores entre o centro de cada divisão do mapa. + /// + /// O mapa + /// Divisão mestre. private void TunnelDivisions(MapData data, MapDivision root) { if (root.IsLeaf) { return; -- cgit v1.2.3