supervisor-simulator/scripts/GameManager.cs

165 lines
4.2 KiB
C#

using Godot;
using System;
using System.Collections.Generic;
using Models;
public partial class GameManager : Node
{
/// <summary>
/// Indicates if the game is currently in tutorial mode.
/// </summary>
public static bool IsTutorial { get; private set; }
public static string NextScene { get; set; } = null;
public static readonly Resource Arrow2x = ResourceLoader.Load("res://temp_res/kenney_ui-pack-space-expansion/PNG/Extra/Double/cursor_f.png");
// --- Core Loop Definitions ---
public enum GamePhase
{
Planning, // 筹备阶段:时间暂停,分配任务,购买设施
Execution, // 执行阶段:时间流动,学生工作
Review, // 结算阶段:回合结束,发工资,结算成果
}
[Export]
public int MaxTurns = 30;
// --- Global State ---
public static GamePhase CurrentPhase { get; private set; } = GamePhase.Planning;
public static int CurrentTurn { get; private set; } = 1;
// --- Domain Model ---
public MentorModel Mentor { get; private set; }
public List<StudentModel> Students { get; private set; } = new List<StudentModel>();
public List<Task> ActiveTasks { get; private set; } = new List<Task>();
// --- Signals ---
[Signal] public delegate void PhaseChangedEventHandler(int phase); // int cast of GamePhase
[Signal] public delegate void TurnChangedEventHandler(int turn);
// Singleton instance access (if needed, though Godot uses node paths)
public static GameManager Instance { get; private set; }
public override void _EnterTree()
{
Instance = this;
}
public override void _Ready()
{
Input.SetCustomMouseCursor(Arrow2x);
// MVP Initialization
InitializeGame();
}
private void InitializeGame()
{
CurrentTurn = 1;
CurrentPhase = GamePhase.Planning;
// MVP: Add a test student
var s1 = new StudentModel("张三");
Students.Add(s1);
// MVP: Add a test task
var t1 = new Task("深度学习导论", TaskType.Paper, 1000f, 3);
ActiveTasks.Add(t1);
GD.Print("Game Initialized. Phase: Planning, Turn: 1");
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
if (CurrentPhase == GamePhase.Execution)
{
// Update game logic (timers, etc.)
// In a real implementation, this might manage the global timer for the day/week
}
}
/// <summary>
/// 结束筹备阶段,开始执行
/// </summary>
public void StartExecution()
{
if (CurrentPhase != GamePhase.Planning) return;
CurrentPhase = GamePhase.Execution;
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Execution");
// Notify all agents to start working (this would be handled by a system listening to the signal)
}
/// <summary>
/// 结束执行阶段(通常由时间耗尽或玩家手动触发),进入结算
/// </summary>
public void EndExecution()
{
if (CurrentPhase != GamePhase.Execution) return;
CurrentPhase = GamePhase.Review;
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
GD.Print("Phase Changed: Review");
PerformReview();
}
/// <summary>
/// 执行结算逻辑,并准备下一回合
/// </summary>
private void PerformReview()
{
// 1. Task progress check
foreach (var task in ActiveTasks)
{
task.Deadline--;
if (task.IsCompleted)
{
GD.Print($"Task {task.Name} Completed!");
Mentor.Reputation += task.RewardReputation;
Mentor.Money += task.RewardMoney;
}
else if (task.IsFailed)
{
GD.Print($"Task {task.Name} Failed!");
Mentor.Reputation -= 10; // Penalty
}
}
// 2. Student status update (Salary, etc.)
foreach (var student in Students)
{
// Deduct salary? Restore some stamina?
}
GD.Print("Review Complete. Waiting for Next Turn confirmation.");
}
/// <summary>
/// 开始新的回合
/// </summary>
public void StartNextTurn()
{
if (CurrentPhase != GamePhase.Review) return;
CurrentTurn++;
if (CurrentTurn > MaxTurns)
{
GD.Print("Game Over!");
// Handle Game Over
return;
}
CurrentPhase = GamePhase.Planning;
EmitSignal(SignalName.TurnChanged, CurrentTurn);
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
// Refresh resources/AP
Mentor.Energy.Current = Mentor.Energy.UpperThreshold;
GD.Print($"Turn {CurrentTurn} Started. Phase: Planning");
}
}