diff options
| author | Matheus <matheus.guedes.mg.m@gmail.com> | 2025-10-30 17:31:00 -0300 |
|---|---|---|
| committer | Matheus <matheus.guedes.mg.m@gmail.com> | 2025-10-30 17:31:06 -0300 |
| commit | d6fc2026917d55fa12713e3d00004ec461cc5971 (patch) | |
| tree | 54fc79f9f8a217b2477721e21875e74c1736564e /scripts | |
| parent | e40bc38dcc17ebeb40722bedb94a6459e47b9aeb (diff) | |
vários andares
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Entities/Actions/TakeStairsAction.cs | 28 | ||||
| -rw-r--r-- | scripts/Entities/Actions/TakeStairsAction.cs.uid | 1 | ||||
| -rw-r--r-- | scripts/InputHandling/MainGameInputHandler.cs | 5 | ||||
| -rw-r--r-- | scripts/Map/DungeonGenerator.cs | 32 | ||||
| -rw-r--r-- | scripts/Map/FieldOfView.cs | 11 | ||||
| -rw-r--r-- | scripts/Map/Map.cs | 50 | ||||
| -rw-r--r-- | scripts/Map/MapData.cs | 10 | ||||
| -rw-r--r-- | scripts/Map/Tile.cs | 6 | ||||
| -rw-r--r-- | scripts/Utils/SignalBus.cs | 3 |
9 files changed, 122 insertions, 24 deletions
diff --git a/scripts/Entities/Actions/TakeStairsAction.cs b/scripts/Entities/Actions/TakeStairsAction.cs new file mode 100644 index 0000000..17fa7e5 --- /dev/null +++ b/scripts/Entities/Actions/TakeStairsAction.cs @@ -0,0 +1,28 @@ +using Godot; +using TheLegendOfGustav.Entities.Actors; +using TheLegendOfGustav.Utils; + +namespace TheLegendOfGustav.Entities.Actions; + +public partial class TakeStairsAction : Action +{ + public TakeStairsAction(Actor actor) : base(actor) + { + cost = 0; + } + + public override bool Perform() + { + if (Actor.GridPosition == MapData.DownstairsLocation) + { + SignalBus.Instance.EmitSignal(SignalBus.SignalName.PlayerDescent); + MessageLogData.Instance.AddMessage("Você desce as escadas..."); + return true; + } + else + { + MessageLogData.Instance.AddMessage("Não tem escadas aqui..."); + return false; + } + } +}
\ No newline at end of file diff --git a/scripts/Entities/Actions/TakeStairsAction.cs.uid b/scripts/Entities/Actions/TakeStairsAction.cs.uid new file mode 100644 index 0000000..03b2448 --- /dev/null +++ b/scripts/Entities/Actions/TakeStairsAction.cs.uid @@ -0,0 +1 @@ +uid://c0adtd8ynoh4q diff --git a/scripts/InputHandling/MainGameInputHandler.cs b/scripts/InputHandling/MainGameInputHandler.cs index bbfb9ca..a18bd73 100644 --- a/scripts/InputHandling/MainGameInputHandler.cs +++ b/scripts/InputHandling/MainGameInputHandler.cs @@ -63,6 +63,11 @@ public partial class MainGameInputHandler : BaseInputHandler action = new EscapeAction(player); } + if (Input.IsActionJustPressed("descend")) + { + action = new TakeStairsAction(player); + } + return action; } } diff --git a/scripts/Map/DungeonGenerator.cs b/scripts/Map/DungeonGenerator.cs index 2d5ef8d..2b24e8a 100644 --- a/scripts/Map/DungeonGenerator.cs +++ b/scripts/Map/DungeonGenerator.cs @@ -2,6 +2,7 @@ using Godot; using TheLegendOfGustav.Entities.Actors; using TheLegendOfGustav.Entities; using TheLegendOfGustav.Entities.Items; +using System; namespace TheLegendOfGustav.Map; @@ -36,16 +37,6 @@ public partial class DungeonGenerator : Node private int height = 60; /// <summary> - /// Qual seed utilizar. - /// </summary> - [Export] - private ulong seed; - /// <summary> - /// Se será utilizada a nossa seed ou a seed padrão da classe RandomNumberGenerator. - /// </summary> - [Export] - private bool useSeed = true; - /// <summary> /// Quantas iterações do algoritmo chamar. /// </summary> [Export] @@ -73,14 +64,6 @@ public partial class DungeonGenerator : Node #endregion #region Methods - public override void _Ready() - { - base._Ready(); - if (useSeed) - { - rng.Seed = seed; - } - } /// <summary> /// Gera um andar da masmorra. @@ -89,9 +72,12 @@ public partial class DungeonGenerator : Node /// </summary> /// <param name="player">Jogador.</param> /// <returns>O mapa gerado.</returns> - public MapData GenerateDungeon(Player player) + public MapData GenerateDungeon(Player player, int currentFloor) { + rng.Seed = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(); + MapData data = new MapData(width, height, player); + data.CurrentFloor = currentFloor; // Divisão mestre que engloba o mapa inteiro. MapDivision root = new MapDivision(0, 0, width, height); @@ -104,6 +90,8 @@ public partial class DungeonGenerator : Node // Coloca os corredores. TunnelDivisions(data, root); + Rect2I lastRoom = new(0, 0, 0, 0); + // Cria as salas com base nas divisões geradas. foreach (MapDivision division in root.GetLeaves()) { @@ -127,8 +115,14 @@ public partial class DungeonGenerator : Node } // Colocamos os inimigos na sala. PlaceEntities(data, room); + + lastRoom = room; } + data.DownstairsLocation = lastRoom!.GetCenter(); + Tile downTile = data.GetTile(data.DownstairsLocation); + downTile.Key = TileType.DOWN_STAIRS; + // Feito o mapa, inicializamos o algoritmo de pathfinding. data.SetupPathfinding(); return data; diff --git a/scripts/Map/FieldOfView.cs b/scripts/Map/FieldOfView.cs index 40df320..474c1ca 100644 --- a/scripts/Map/FieldOfView.cs +++ b/scripts/Map/FieldOfView.cs @@ -101,6 +101,17 @@ public partial class FieldOfView : Node fov.Clear(); } + /// <summary> + /// Diferença de ClearFOV: não referencia tiles. + /// No contexto onde ResetFOV é chamado, os tiles não + /// podem ser referenciados porque já foram liberados da + /// memória. + /// </summary> + public void ResetFOV() + { + fov.Clear(); + } + public void UpdateFOV(MapData data, Vector2I position, int radius) { ClearFOV(); diff --git a/scripts/Map/Map.cs b/scripts/Map/Map.cs index 04ccabd..2913c1f 100644 --- a/scripts/Map/Map.cs +++ b/scripts/Map/Map.cs @@ -2,6 +2,7 @@ using System.Net.Http.Headers; using Godot; using TheLegendOfGustav.Entities; using TheLegendOfGustav.Entities.Actors; +using TheLegendOfGustav.Utils; namespace TheLegendOfGustav.Map; @@ -30,7 +31,11 @@ public partial class Map : Node2D /// Dados do mapa. /// </summary> public MapData MapData { get; private set; } - + + [Signal] + public delegate void DungeonFloorChangedEventHandler(int floor); + + private SignalBus.PlayerDescentEventHandler joinSignal; public override void _Ready() { base._Ready(); @@ -39,20 +44,46 @@ public partial class Map : Node2D fieldOfView = GetNode<FieldOfView>("FieldOfView"); tilesNode = GetNode<Node2D>("Tiles"); entitiesNode = GetNode<Node2D>("Entities"); + + joinSignal = () => NextFloor(); + SignalBus.Instance.PlayerDescent += joinSignal; + } + + void NextFloor() + { + Player player = MapData.Player; + entitiesNode.RemoveChild(player); + + foreach (var entity in entitiesNode.GetChildren()) + { + entity.QueueFree(); + } + + foreach (var tile in tilesNode.GetChildren()) + { + tile.QueueFree(); + } + + Generate(player, MapData.CurrentFloor + 1); + player.GetNode<Camera2D>("Camera2D").MakeCurrent(); + fieldOfView.ResetFOV(); + UpdateFOV(player.GridPosition); } /// <summary> /// Cria um andar da masmorra utilizando o gerador de mapa. /// </summary> /// <param name="player">O gerador de mapas precisa do jogador.</param> - public void Generate(Player player) + public void Generate(Player player, int currentFloor = 1) { - MapData = generator.GenerateDungeon(player); + MapData = generator.GenerateDungeon(player, currentFloor); MapData.EntityPlaced += OnEntityPlaced; PlaceTiles(); PlaceEntities(); + + EmitSignal(SignalName.DungeonFloorChanged, currentFloor); } /// <summary> @@ -111,6 +142,19 @@ public partial class Map : Node2D PlaceEntities(); MapData.EntityPlaced += OnEntityPlaced; + EmitSignal(SignalName.DungeonFloorChanged, MapData.CurrentFloor); return true; } + + public override void _Notification(int what) + { + if (what == NotificationPredelete) + { + if (joinSignal != null) + { + SignalBus.Instance.PlayerDescent -= joinSignal; + } + } + base._Notification(what); + } } diff --git a/scripts/Map/MapData.cs b/scripts/Map/MapData.cs index 5f96743..907e8d0 100644 --- a/scripts/Map/MapData.cs +++ b/scripts/Map/MapData.cs @@ -84,6 +84,10 @@ public partial class MapData : RefCounted, ISaveable return list; } } + + public int CurrentFloor { get; set; } = 0; + + public Vector2I DownstairsLocation { get; set; } /// <summary> /// Objeto do Godot que utiliza do algoritmo A* para calcular /// caminhos e rotas. @@ -349,6 +353,9 @@ public partial class MapData : RefCounted, ISaveable {"player", Player.GetSaveData()}, {"width", Width}, {"height", Height}, + {"current_floor", CurrentFloor}, + {"down_stairs_location_x", DownstairsLocation.X}, + {"down_stairs_location_y", DownstairsLocation.Y} }; } @@ -357,6 +364,9 @@ public partial class MapData : RefCounted, ISaveable Width = (int)saveData["width"]; Height = (int)saveData["height"]; + CurrentFloor = (int)saveData["current_floor"]; + DownstairsLocation = new((int)saveData["down_stairs_location_x"], (int)saveData["down_stairs_location_y"]); + SetupTiles(); Array<Dictionary<string, Variant>> serializedTiles = (Array<Dictionary<string, Variant>>)saveData["tiles"]; diff --git a/scripts/Map/Tile.cs b/scripts/Map/Tile.cs index 6790f3e..03039e0 100644 --- a/scripts/Map/Tile.cs +++ b/scripts/Map/Tile.cs @@ -8,7 +8,8 @@ namespace TheLegendOfGustav.Map; public enum TileType { WALL, - FLOOR + FLOOR, + DOWN_STAIRS } /// <summary> @@ -22,7 +23,8 @@ public partial class Tile : Sprite2D, ISaveable private static readonly Godot.Collections.Dictionary<TileType, TileDefinition> Types = new() { {TileType.WALL, GD.Load<TileDefinition>("res://assets/definitions/tiles/wall.tres")}, - {TileType.FLOOR, GD.Load<TileDefinition>("res://assets/definitions/tiles/floor.tres")} + {TileType.FLOOR, GD.Load<TileDefinition>("res://assets/definitions/tiles/floor.tres")}, + {TileType.DOWN_STAIRS, GD.Load<TileDefinition>("res://assets/definitions/tiles/downstairs.tres")} }; TileType key; diff --git a/scripts/Utils/SignalBus.cs b/scripts/Utils/SignalBus.cs index 291ffcd..a7eccf8 100644 --- a/scripts/Utils/SignalBus.cs +++ b/scripts/Utils/SignalBus.cs @@ -34,6 +34,9 @@ public partial class SignalBus : Node [Signal] public delegate void EscapeRequestedEventHandler(); + [Signal] + public delegate void PlayerDescentEventHandler(); + public override void _Ready() { base._Ready(); |
