221 lines
6.4 KiB
C#
221 lines
6.4 KiB
C#
using System.Collections.Generic;
|
||
using Core;
|
||
using Godot;
|
||
using Models;
|
||
|
||
/// <summary>
|
||
/// 游戏主控制节点(MVC 的桥接层)
|
||
/// 设计说明:
|
||
/// 1) 负责初始化 GameSession,并把输入/信号转交给 Controller/System。
|
||
/// 2) 仅做“流程调度”,不直接计算复杂数值,避免逻辑堆积。
|
||
/// 注意事项:
|
||
/// - View 与 Model 的绑定应逐步迁移到独立 View 脚本,避免在此类膨胀。
|
||
/// 未来扩展:
|
||
/// - 可拆分为 SceneRoot + UIController + DebugController,分层管理。
|
||
/// </summary>
|
||
public partial class GameManager : Node {
|
||
// --- Signals ---
|
||
/// <summary>
|
||
/// 阶段变更信号
|
||
/// </summary>
|
||
/// <param name="phase">阶段枚举的整数值</param>
|
||
[Signal]
|
||
public delegate void PhaseChangedEventHandler(int phase); // int cast of GamePhase
|
||
|
||
/// <summary>
|
||
/// 回合变更信号
|
||
/// </summary>
|
||
/// <param name="turn">当前回合数</param>
|
||
[Signal]
|
||
public delegate void TurnChangedEventHandler(int turn);
|
||
|
||
/// <summary>
|
||
/// 双倍大小的箭头光标资源
|
||
/// </summary>
|
||
public static readonly Resource Arrow2X =
|
||
ResourceLoader.Load("res://temp_res/kenney_ui-pack-space-expansion/PNG/Extra/Double/cursor_f.png");
|
||
|
||
/// <summary>
|
||
/// 最大回合数
|
||
/// </summary>
|
||
[Export] public int MaxTurns = 30;
|
||
|
||
/// <summary>
|
||
/// 指示当前是否处于教程模式
|
||
/// </summary>
|
||
public static bool IsTutorial { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 下一个场景的路径
|
||
/// </summary>
|
||
public static string NextScene { get; set; } = null;
|
||
|
||
// --- Global State ---
|
||
|
||
/// <summary>
|
||
/// 游戏会话实例
|
||
/// </summary>
|
||
public GameSession Session { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 当前游戏状态
|
||
/// </summary>
|
||
public GameState State => Session?.State;
|
||
|
||
/// <summary>
|
||
/// 游戏控制器
|
||
/// </summary>
|
||
public GameController Controller { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 当前游戏阶段
|
||
/// </summary>
|
||
public GamePhase CurrentPhase => State?.Turn.Phase ?? GamePhase.Planning;
|
||
|
||
/// <summary>
|
||
/// 当前回合数
|
||
/// </summary>
|
||
public int CurrentTurn => State?.Turn.CurrentTurn ?? 1;
|
||
|
||
// --- Domain Model ---
|
||
|
||
/// <summary>
|
||
/// 导师模型
|
||
/// </summary>
|
||
public MentorModel Mentor => State?.Roster.Mentor;
|
||
|
||
/// <summary>
|
||
/// 学生列表
|
||
/// </summary>
|
||
public List<StudentModel> Students => State?.Roster.Students;
|
||
|
||
/// <summary>
|
||
/// 当前活动任务列表
|
||
/// </summary>
|
||
public List<TaskModel> ActiveTasks => State?.Tasks.ActiveTasks;
|
||
|
||
/// <summary>
|
||
/// 经济状态
|
||
/// </summary>
|
||
public EconomyState Economy => State?.Economy;
|
||
|
||
// Singleton instance access (if needed, though Godot uses node paths)
|
||
/// <summary>
|
||
/// 单例实例
|
||
/// </summary>
|
||
public static GameManager Instance { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 进入场景树时调用
|
||
/// </summary>
|
||
public override void _EnterTree() {
|
||
Instance = this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 准备就绪时调用
|
||
/// </summary>
|
||
public override void _Ready() {
|
||
Input.SetCustomMouseCursor(Arrow2X);
|
||
|
||
// MVP Initialization
|
||
InitializeGame();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化游戏数据
|
||
/// </summary>
|
||
private void InitializeGame() {
|
||
Session = GameSession.CreateDefault();
|
||
Controller = new GameController();
|
||
Controller.Initialize(Session);
|
||
State.Turn.MaxTurns = MaxTurns;
|
||
State.Turn.CurrentTurn = 1;
|
||
State.Turn.Phase = GamePhase.Planning;
|
||
|
||
// MVP: Add a test student
|
||
var s1 = new StudentModel("张三");
|
||
Students.Add(s1);
|
||
|
||
// MVP: Add a test task
|
||
var t1 = new TaskModel("深度学习导论", TaskKind.AcademicExploration, 1000f, 3);
|
||
t1.Reward.Money = 1000;
|
||
t1.Reward.Reputation = 5;
|
||
ActiveTasks.Add(t1);
|
||
|
||
GD.Print("Game Initialized. Phase: Planning, Turn: 1");
|
||
}
|
||
|
||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||
/// <summary>
|
||
/// 每帧调用
|
||
/// </summary>
|
||
/// <param name="delta">距离上一帧的时间间隔</param>
|
||
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
|
||
}
|
||
|
||
Session?.Tick((float)delta);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结束筹备阶段,开始执行
|
||
/// </summary>
|
||
public void StartExecution() {
|
||
if (CurrentPhase != GamePhase.Planning) return;
|
||
|
||
Controller.StartExecution();
|
||
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;
|
||
|
||
Controller.EndExecution();
|
||
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
|
||
GD.Print("Phase Changed: Review");
|
||
|
||
PerformReview();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行结算逻辑,并准备下一回合
|
||
/// </summary>
|
||
private void PerformReview() {
|
||
Session.Systems.Task.ResolveEndOfTurn();
|
||
Session.Events.Publish(new TurnEndedEvent(CurrentTurn));
|
||
|
||
GD.Print("Review Complete. Waiting for Next Turn confirmation.");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开始新的回合
|
||
/// </summary>
|
||
public void StartNextTurn() {
|
||
if (CurrentPhase != GamePhase.Review) return;
|
||
|
||
Controller.StartNextTurn();
|
||
if (CurrentTurn > State.Turn.MaxTurns) {
|
||
GD.Print("Game Over!");
|
||
// Handle Game Over
|
||
return;
|
||
}
|
||
|
||
State.Turn.Phase = GamePhase.Planning;
|
||
EmitSignal(SignalName.TurnChanged, CurrentTurn);
|
||
EmitSignal(SignalName.PhaseChanged, (int)CurrentPhase);
|
||
|
||
// Refresh resources/AP
|
||
Mentor.Resources.Energy.Current.Value = Mentor.Resources.Energy.UpperThreshold;
|
||
|
||
GD.Print($"Turn {CurrentTurn} Started. Phase: Planning");
|
||
}
|
||
} |