summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMatheus <matheus.guedes.mg.m@gmail.com>2025-08-31 09:51:19 -0300
committerMatheus <matheus.guedes.mg.m@gmail.com>2025-08-31 09:51:19 -0300
commitd7d2454d5ccc1e0acb47cb679c7550e74c4e1916 (patch)
treed00941e010a0e84eca966fc8a0cdef0e67ebeedb /scripts
parentdac21a6dcb74be03dc1cde0798d09042beb558c9 (diff)
Sistema de turnos separado
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Game.cs52
-rw-r--r--scripts/Time/TurnManager.cs103
-rw-r--r--scripts/Time/TurnManager.cs.uid1
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