diff options
| author | Matheus <matheus.guedes.mg.m@gmail.com> | 2025-08-31 09:51:19 -0300 |
|---|---|---|
| committer | Matheus <matheus.guedes.mg.m@gmail.com> | 2025-08-31 09:51:19 -0300 |
| commit | d7d2454d5ccc1e0acb47cb679c7550e74c4e1916 (patch) | |
| tree | d00941e010a0e84eca966fc8a0cdef0e67ebeedb | |
| parent | dac21a6dcb74be03dc1cde0798d09042beb558c9 (diff) | |
Sistema de turnos separado
| -rw-r--r-- | scripts/Game.cs | 52 | ||||
| -rw-r--r-- | scripts/Time/TurnManager.cs | 103 | ||||
| -rw-r--r-- | scripts/Time/TurnManager.cs.uid | 1 |
3 files changed, 115 insertions, 41 deletions
diff --git a/scripts/Game.cs b/scripts/Game.cs index 981699d..58a5957 100644 --- a/scripts/Game.cs +++ b/scripts/Game.cs @@ -18,6 +18,10 @@ public partial class Game : Node { /// Objeto para obter input do usuário. /// </summary> private InputHandler inputHandler; + /// <summary> + /// Gerenciador de turnos + /// </summary> + private TurnManager turnManager; private UI ui; @@ -41,6 +45,8 @@ public partial class Game : Node { Map.Generate(player); Map.UpdateFOV(player.GridPosition); + + turnManager = new(Map); } /// <summary> @@ -55,48 +61,12 @@ public partial class Game : Node { // Pegamos uma ação do usuário Action action = inputHandler.GetAction(player); - // Se realmente houve uma ação ou se o jogador não puder agir, computamos um turno. - if (action != null || player.Energy < 0) { - Vector2I previousPlayerPos = player.GridPosition; - - // Início do turno, o jogador recebe um pouco de energia. - if (player.Energy <= 0) { - player.RechargeEnergy(); - } - - // Primeiro executamos a ação do jogador - action?.Perform(); - - // Se o jogador ainda tem energia, ele poderá fazer - // mais um turno sem interrupções. - if (player.Energy <= 0) { - // Depois computamos os turnos dos outros atores. - HandleEnemyTurns(); - } - // Por fim, se o jogador mudou de lugar, atualizamos seu campo de visão. - if (player.GridPosition != previousPlayerPos) { - Map.UpdateFOV(player.GridPosition); - } + if (action != null) { + turnManager.InsertPlayerAction(action); } - } - /// <summary> - /// Executa turnos para cada ator no mapa. - /// </summary> - private void HandleEnemyTurns() { - foreach (Actor actor in Map.Map_Data.Actors) { - if (actor is Player) continue; - // Se o ator for um inimigo e estiver vivo, deixamos - // que sua IA faça um turno. - if (actor is Enemy enemy && enemy.IsAlive) { - // Início do turno, inimigo recebe energia. - enemy.RechargeEnergy(); - - // O inimigo poderá fazer quantos turnos sua energia deixar. - while (enemy.Energy > 0) { - enemy.Soul.Perform(); - } - } - } + // Computamos um turno. + turnManager.Tick(); } + } diff --git a/scripts/Time/TurnManager.cs b/scripts/Time/TurnManager.cs new file mode 100644 index 0000000..0c2981c --- /dev/null +++ b/scripts/Time/TurnManager.cs @@ -0,0 +1,103 @@ +using Godot; + +/// <summary> +/// Gerenciador de turnos, o senhor do tempo. +/// </summary> +public partial class TurnManager : RefCounted +{ + public int TurnCount { get; private set; } = 0; + private Map map; + private MapData Map_Data { get => map.Map_Data; } + private Player Player { get => Map_Data.Player; } + + /// <summary> + /// As ações do jogador ficam em uma fila e são executadas quando + /// possível dentro das regras do senhor do tempo. + /// </summary> + private Godot.Collections.Array<Action> playerActionQueue = []; + + public TurnManager(Map map) { + this.map = map; + } + + /// <summary> + /// Insere uma ação na fila de ações do jogador. + /// </summary> + /// <param name="playerAction"></param> + public void InsertPlayerAction(Action playerAction) { + playerActionQueue.Add(playerAction); + } + + /// <summary> + /// Computa um turno. + /// + /// Um turno segue a seguinte ordem lógica + /// 1. Todos os atores recebem energia com base nas suas velocidades. + /// 2. O jogador performa ações enquanto sua energia permitir + /// 3. Os outros atores performam suas ações enquanto sua energia permitir. + /// </summary> + public void Tick() { + // Se o jogador puder agir mas a fila de ações estiver vazia, + // não computamos o turno. + if (playerActionQueue.Count == 0 && Player.Energy > 0) { + return; + } + + Vector2I previousPlayerPos = Player.GridPosition; + + // Início do turno, o jogador recebe um pouco de energia. + if (Player.Energy <= 0) { + StartTurn(); + } + + // Primeiro executamos a ação do jogador, se ele puder. + if (Player.Energy > 0) { + Action action = playerActionQueue[0]; + playerActionQueue.RemoveAt(0); + + action.Perform(); + } + + // Se o jogador ainda tem energia, ele poderá fazer + // mais um turno sem interrupções. + if (Player.Energy <= 0) { + // Depois computamos os turnos dos outros atores. + HandleEnemyTurns(); + } + // Por fim, se o jogador mudou de lugar, atualizamos seu campo de visão. + if (Player.GridPosition != previousPlayerPos) { + map.UpdateFOV(Player.GridPosition); + } + } + + /// <summary> + /// Método executado no início do turno. + /// </summary> + private void StartTurn() { + TurnCount++; + + // Recarregamos a energia de todos os atores. + foreach (Actor actor in Map_Data.Actors) { + if (actor.IsAlive) { + actor.RechargeEnergy(); + } + } + } + + /// <summary> + /// Executa turnos para cada ator no mapa. + /// </summary> + private void HandleEnemyTurns() { + foreach (Actor actor in Map_Data.Actors) { + if (actor is Player) continue; + // Se o ator for um inimigo e estiver vivo, deixamos + // que sua IA faça um turno. + if (actor is Enemy enemy && enemy.IsAlive) { + // O inimigo poderá fazer quantos turnos sua energia deixar. + while (enemy.Energy > 0) { + enemy.Soul.Perform(); + } + } + } + } +} diff --git a/scripts/Time/TurnManager.cs.uid b/scripts/Time/TurnManager.cs.uid new file mode 100644 index 0000000..1a61168 --- /dev/null +++ b/scripts/Time/TurnManager.cs.uid @@ -0,0 +1 @@ +uid://dfaqjqa1txypn |
