diff --git a/scripts/Campus/CampusBehaviorAgent.cs b/scripts/Campus/CampusBehaviorAgent.cs
index 467ae4a..7eb6d2d 100644
--- a/scripts/Campus/CampusBehaviorAgent.cs
+++ b/scripts/Campus/CampusBehaviorAgent.cs
@@ -4,8 +4,8 @@ using Godot;
using Models;
///
-/// Runtime data for a campus agent. This keeps Godot nodes and pure data separate
-/// so the behavior system can be tested without scene dependencies.
+/// 校园代理的运行时数据。将 Godot 节点与纯数据分离,
+/// 以便行为系统可以在没有场景依赖的情况下进行测试。
///
public sealed class CampusAgentRuntime
{
@@ -34,8 +34,8 @@ public sealed class CampusAgentRuntime
}
///
-/// Intent produced by the planner. It captures both the action and the destination,
-/// plus an optional planned duration for round-based schedules.
+/// 规划器生成的意图。它捕获了行动和目的地,
+/// 加上可选的轮次计划持续时间。
///
public sealed class CampusBehaviorIntent
{
@@ -62,8 +62,8 @@ public sealed class CampusBehaviorIntent
}
///
-/// Shared context passed into providers/states so they can evaluate the same data
-/// without hard-coding dependencies.
+/// 传递给提供者/状态的共享上下文,以便它们可以评估相同的数据
+/// 而无需硬编码依赖关系。
///
public sealed class CampusBehaviorContext
{
@@ -92,8 +92,8 @@ public sealed class CampusBehaviorContext
}
///
-/// Providers represent a single rule in the priority queue. Each provider returns
-/// a behavior intent or null if it cannot apply to the current context.
+/// 提供者表示优先级队列中的单个规则。
+/// 每个提供者返回一个行为意图,或者如果它不能应用于当前上下文,则返回 null。
///
public interface ICampusBehaviorProvider
{
@@ -101,8 +101,8 @@ public interface ICampusBehaviorProvider
}
///
-/// Critical state provider: handles sanity collapse, extreme stress, or exhaustion.
-/// This is the highest priority in the decision queue.
+/// 紧急状态提供者:处理理智崩溃、极度压力或力竭。
+/// 这是决策队列中的最高优先级。
///
public sealed class CriticalBehaviorProvider : ICampusBehaviorProvider
{
@@ -153,7 +153,7 @@ public sealed class CriticalBehaviorProvider : ICampusBehaviorProvider
}
///
-/// Assigned task provider: if the agent has a task, it is executed before needs.
+/// 指派任务提供者:如果代理有任务,则在需求之前执行。
///
public sealed class AssignedTaskBehaviorProvider : ICampusBehaviorProvider
{
@@ -188,8 +188,8 @@ public sealed class AssignedTaskBehaviorProvider : ICampusBehaviorProvider
}
///
-/// Needs provider: hunger, fatigue, mood, and social needs are handled here.
-/// It sits below assigned tasks but above trait-driven idle behavior.
+/// 需求提供者:处理饥饿、疲劳、情绪和社交需求。
+/// 它位于指派任务之下,但在特质驱动的空闲行为之上。
///
public sealed class NeedsBehaviorProvider : ICampusBehaviorProvider
{
@@ -273,8 +273,7 @@ public sealed class NeedsBehaviorProvider : ICampusBehaviorProvider
}
///
-/// Trait-driven provider: applies long-term personality or tag tendencies when
-/// there is no urgent need.
+/// 特质驱动提供者:当没有紧急需求时,应用长期性格或标签倾向。
///
public sealed class TraitBehaviorProvider : ICampusBehaviorProvider
{
@@ -405,7 +404,7 @@ public sealed class TraitBehaviorProvider : ICampusBehaviorProvider
}
///
-/// Idle provider: default fallback when nothing else applies.
+/// 闲置提供者:当没有其他适用规则时的默认后备方案。
///
public sealed class IdleBehaviorProvider : ICampusBehaviorProvider
{
@@ -420,8 +419,8 @@ public sealed class IdleBehaviorProvider : ICampusBehaviorProvider
}
///
-/// Planner executes providers in priority order. This lets us add or remove
-/// providers without editing the state machine.
+/// 规划器按优先级顺序执行提供者。这允许我们添加或删除提供者
+/// 而无需编辑状态机。
///
public sealed class CampusBehaviorPlanner
{
@@ -448,8 +447,7 @@ public sealed class CampusBehaviorPlanner
}
///
-/// State interface for the AI FSM. Each state can transition by requesting
-/// a change via the owning behavior agent.
+/// AI FSM 的状态接口。每个状态可以通过请求更改来转换。
///
public interface ICampusBehaviorState
{
@@ -459,7 +457,7 @@ public interface ICampusBehaviorState
}
///
-/// State machine wrapper to enforce enter/exit semantics.
+/// 状态机包装器,用于强制执行进入/退出语义。
///
public sealed class CampusBehaviorStateMachine
{
@@ -479,8 +477,8 @@ public sealed class CampusBehaviorStateMachine
}
///
-/// Decision state: pick a new intent and immediately transition to movement.
-/// This keeps the intent selection isolated and easy to extend.
+/// 决策状态:选择一个新的意图并立即转换为移动。
+/// 这使意图选择隔离且易于扩展。
///
public sealed class CampusDecisionState : ICampusBehaviorState
{
@@ -500,8 +498,8 @@ public sealed class CampusDecisionState : ICampusBehaviorState
}
///
-/// Movement state: navigate to the intent's target location.
-/// Once the agent arrives, it transitions into the action state.
+/// 移动状态:导航到意图的目标位置。
+/// 一旦代理到达,它将转换为动作状态。
///
public sealed class CampusMoveState : ICampusBehaviorState
{
@@ -534,8 +532,8 @@ public sealed class CampusMoveState : ICampusBehaviorState
}
///
-/// Action state: apply per-second deltas and update task progress.
-/// When the action duration expires, transition back to decision.
+/// 动作状态:应用每秒增量并更新任务进度。
+/// 当动作持续时间结束时,转回决策状态。
///
public sealed class CampusActionState : ICampusBehaviorState
{
@@ -642,8 +640,8 @@ public sealed class CampusActionState : ICampusBehaviorState
}
///
-/// Main behavior agent that drives one campus character. It owns the planner,
-/// state machine, and applies baseline stat decay on every tick.
+/// 驱动一个校园角色的主要行为代理。它拥有规划器、
+/// 状态机,并在每次 Tick 时应用基线属性衰减。
///
public sealed class CampusBehaviorAgent
{
@@ -1088,8 +1086,8 @@ public sealed class CampusBehaviorAgent
}
///
-/// Centralized IDs for traits referenced by the behavior system.
-/// Keeping them here avoids scattering magic strings.
+/// 行为系统引用的特质的集中 ID。
+/// 将它们放在这里可以避免分散的魔法字符串。
///
public static class CampusTraitIds
{
@@ -1098,4 +1096,4 @@ public static class CampusTraitIds
public const string SocialButterfly = "core:trait_social_butterfly";
public const string NotHuman = "core:trait_not_human";
public const string BigEater = "core:trait_big_eater";
-}
+}
\ No newline at end of file
diff --git a/scripts/Campus/CampusBehaviorConfig.cs b/scripts/Campus/CampusBehaviorConfig.cs
index 13f0f75..7df3b35 100644
--- a/scripts/Campus/CampusBehaviorConfig.cs
+++ b/scripts/Campus/CampusBehaviorConfig.cs
@@ -7,72 +7,72 @@ using Godot;
using Models;
///
-/// Location identifiers used by the campus behavior system.
-/// These map to Node2D markers in campus.tscn so the AI can pick targets by name.
+/// 校园行为系统使用的位置标识符。
+/// 这些标识符映射到 campus.tscn 中的 Node2D 标记点,以便 AI 可以通过名称选择目标。
///
public enum CampusLocationId
{
None,
- Laboratory,
- Library,
- Canteen,
- Dormitory,
- ArtificialLake,
- CoffeeShop,
- AdministrationBuilding,
- FootballField,
- RandomWander
+ Laboratory, // 实验室
+ Library, // 图书馆
+ Canteen, // 食堂
+ Dormitory, // 宿舍
+ ArtificialLake, // 人工湖
+ CoffeeShop, // 咖啡店
+ AdministrationBuilding, // 行政楼
+ FootballField, // 足球场
+ RandomWander // 随机漫游
}
///
-/// Action identifiers used by the behavior planner and state machine.
-/// Each action is configured via campus_behavior.json for duration and stat deltas.
+/// 行为规划器和状态机使用的动作标识符。
+/// 每个动作通过 campus_behavior.json 配置持续时间和属性变化。
///
public enum CampusActionId
{
None,
- Experimenting,
- Writing,
- Eating,
- Sleeping,
- Chilling,
- Staring,
- CoffeeBreak,
- Administration,
- Running,
- Socializing,
- Wandering
+ Experimenting, // 做实验
+ Writing, // 写作
+ Eating, // 吃饭
+ Sleeping, // 睡觉
+ Chilling, // 放松/闲逛
+ Staring, // 发呆
+ CoffeeBreak, // 喝咖啡
+ Administration, // 行政工作
+ Running, // 跑步
+ Socializing, // 社交
+ Wandering // 漫步
}
///
-/// Priority levels match the design doc ordering: lower value = higher priority.
+/// 优先级级别,对应设计文档中的顺序:值越小优先级越高。
///
public enum CampusBehaviorPriority
{
- Critical = 0,
- AssignedTask = 1,
- Needs = 2,
- Trait = 3,
- Idle = 4
+ Critical = 0, // 紧急状态(崩溃/力竭)
+ AssignedTask = 1, // 指派任务
+ Needs = 2, // 基础需求(饿/累/社交)
+ Trait = 3, // 特质驱动(性格偏好)
+ Idle = 4 // 闲置
}
///
-/// Minimal task types for the campus demo. These are not full gameplay tasks,
-/// just drivers for the assigned-task priority in the AI.
+/// 校园演示的最小化任务类型。这些不是完整的游戏任务,
+/// 仅用于驱动 AI 的“指派任务”优先级。
///
public enum CampusTaskType
{
- Experiment,
- Writing,
- Administration,
- Exercise,
- Coding,
- Social
+ Experiment, // 实验
+ Writing, // 写作
+ Administration, // 行政
+ Exercise, // 锻炼
+ Coding, // 编程
+ Social // 社交
}
///
-/// Action configuration loaded from JSON. Deltas are applied per second while
-/// the action is running, so longer actions accumulate more effect.
+/// 从 JSON 加载的动作配置。
+/// 变化量(Delta)在动作运行时按秒应用,因此动作越长积累的效果越多。
///
public sealed class CampusActionConfig
{
@@ -90,8 +90,8 @@ public sealed class CampusActionConfig
}
///
-/// Global behavior configuration for campus AI. This is intentionally data-driven
-/// so balancing can happen in JSON without touching code.
+/// 校园 AI 的全局行为配置。
+/// 这是数据驱动的,以便在不修改代码的情况下通过 JSON 进行平衡调整。
///
public sealed class CampusBehaviorConfig
{
@@ -179,8 +179,8 @@ public sealed class CampusBehaviorConfig
}
///
-/// Simple location registry that maps logical location ids to scene positions.
-/// This keeps the behavior system independent from scene tree details.
+/// 简单的位置注册表,将逻辑位置 ID 映射到场景位置。
+/// 保持行为系统独立于场景树细节。
///
public sealed class CampusLocationRegistry
{
@@ -199,8 +199,8 @@ public sealed class CampusLocationRegistry
}
///
-/// Tracks current occupancy per location so traits like social phobia can react
-/// to crowd size without hard-coding scene knowledge.
+/// 跟踪每个位置的当前占用情况,以便像社交恐惧症这样的特质可以根据人群规模做出反应,
+/// 而无需硬编码场景知识。
///
public sealed class CampusBehaviorWorld
{
@@ -229,7 +229,7 @@ public sealed class CampusBehaviorWorld
}
///
-/// Lightweight task container for the campus demo; it just tracks remaining work.
+/// 校园演示的轻量级任务容器;它只跟踪剩余工作量。
///
public sealed class CampusTask
{
@@ -251,8 +251,8 @@ public sealed class CampusTask
}
///
-/// Custom needs that are not yet part of the core UnitModel (hunger/social/energy).
-/// Uses PropertyValue so it plugs into the existing numeric system.
+/// 自定义需求,尚未成为核心 UnitModel 的一部分(饥饿/社交/精力)。
+/// 使用 PropertyValue 以便接入现有的数值系统。
///
public sealed class CampusAgentNeeds
{
@@ -268,4 +268,4 @@ public sealed class CampusAgentNeeds
Social = new PropertyValue(social);
Health = new PropertyValue(health);
}
-}
+}
\ No newline at end of file
diff --git a/scripts/CampusStudent.cs b/scripts/CampusStudent.cs
index 5b81c6a..0a4d557 100644
--- a/scripts/CampusStudent.cs
+++ b/scripts/CampusStudent.cs
@@ -3,63 +3,238 @@ using System.Collections.Generic;
using System.Diagnostics;
using Godot;
+///
+/// 校园学生角色控制器
+///
public partial class CampusStudent : CharacterBody2D
{
+ ///
+ /// 饰品精灵
+ ///
private Sprite2D _accessory;
+ ///
+ /// 动画播放器
+ ///
private AnimationPlayer _animationPlayer;
+ ///
+ /// 身体精灵
+ ///
private Sprite2D _body;
+ ///
+ /// 眼睛精灵
+ ///
private Sprite2D _eye;
+ ///
+ /// 发型精灵
+ ///
private Sprite2D _hairstyle;
+ ///
+ /// 上一帧的时间间隔
+ ///
private double _lastDelta;
+
+ ///
+ /// 面朝方向
+ ///
+ private enum FacingDirection
+ {
+ Up,
+ Down,
+ Left,
+ Right
+ }
+
+ ///
+ /// 上一次的面朝方向
+ ///
private FacingDirection _lastFacing = FacingDirection.Down;
+ ///
+ /// 上一次的位置
+ ///
private Vector2 _lastPosition;
+ ///
+ /// 导航代理
+ ///
private NavigationAgent2D _navigationAgent;
+ ///
+ /// 服装精灵
+ ///
private Sprite2D _outfit;
+ ///
+ /// 是否已配置巡逻
+ ///
private bool _patrolConfigured;
+ ///
+ /// 当前巡逻点索引
+ ///
private int _patrolIndex;
+ ///
+ /// 巡逻点列表
+ ///
private List _patrolPoints = new();
+ ///
+ /// 手机精灵
+ ///
private Sprite2D _smartphone;
+ ///
+ /// 卡住计时器
+ ///
private float _stuckTimer;
+ ///
+ /// 导航地图RID
+ ///
private Rid _navigationMap;
+ ///
+ /// 当前目标点
+ ///
private Vector2 _currentTarget = Vector2.Zero;
+ ///
+ /// 是否有目标
+ ///
private bool _hasTarget;
+ ///
+ /// 是否启用行为控制
+ ///
private bool _behaviorControlEnabled;
+ ///
+ /// 行为目标点
+ ///
private Vector2 _behaviorTarget = Vector2.Zero;
+ ///
+ /// 是否有行为目标
+ ///
private bool _behaviorHasTarget;
+ ///
+ /// 手机闲置动画是否激活
+ ///
private bool _phoneIdleActive;
+ ///
+ /// 手机退出动作锁定
+ ///
private bool _phoneExitLocked;
+ ///
+ /// 是否使用物理移动
+ ///
private bool _usePhysicsMovement = true;
+ ///
+ /// 网格路径列表
+ ///
private readonly List _gridPath = new();
+ ///
+ /// 当前网格路径索引
+ ///
private int _gridPathIndex;
+ ///
+ /// 网格路径是否激活
+ ///
private bool _gridPathActive;
+ ///
+ /// 网格路径是否挂起
+ ///
private bool _gridPathPending;
+ ///
+ /// AStar网格
+ ///
private AStarGrid2D _astarGrid;
+ ///
+ /// AStar区域
+ ///
private Rect2I _astarRegion;
+ ///
+ /// AStar地图迭代版本
+ ///
private int _astarMapIteration;
+ ///
+ /// 网格重新寻路重试计时器
+ ///
private float _gridPathRetryTimer;
+ ///
+ /// 导航区域引用
+ ///
private NavigationRegion2D _navigationRegion;
+
+ ///
+ /// 移动速度
+ ///
[Export] public float MoveSpeed { get; set; } = 60.0f;
+ ///
+ /// 目标到达判定距离
+ ///
[Export] public float TargetReachDistance { get; set; } = 6.0f;
+ ///
+ /// 是否使用16x16精灵
+ ///
[Export] public bool Use16X16Sprites { get; set; } = true;
+ ///
+ /// 是否启用避让
+ ///
[Export] public bool EnableAvoidance { get; set; }
+ ///
+ /// 卡住重新寻路时间
+ ///
[Export] public float StuckRepathSeconds { get; set; } = 0.6f;
+ ///
+ /// 卡住距离阈值
+ ///
[Export] public float StuckDistanceEpsilon { get; set; } = 2.0f;
+ ///
+ /// 导航网格吸附距离
+ ///
[Export] public float NavMeshClampDistance { get; set; } = 6.0f;
+ ///
+ /// 是否使用网格寻路
+ ///
[Export] public bool UseGridPathfinding { get; set; } = true;
+ ///
+ /// 网格单元大小
+ ///
[Export] public float GridCellSize { get; set; } = 8.0f;
+ ///
+ /// 网格可行走容差
+ ///
[Export] public float GridWalkableTolerance { get; set; } = 2.0f;
+ ///
+ /// 网格搜索节点限制
+ ///
[Export] public int GridSearchNodeLimit { get; set; } = 8000;
+ ///
+ /// 网格重新寻路间隔
+ ///
[Export] public float GridRepathInterval { get; set; } = 0.25f;
+ ///
+ /// 调试绘制网格
+ ///
[Export] public bool DebugDrawGrid { get; set; }
+ ///
+ /// 调试仅绘制实心点
+ ///
[Export] public bool DebugDrawSolidOnly { get; set; } = true;
+ ///
+ /// 调试绘制路径
+ ///
[Export] public bool DebugDrawPath { get; set; }
+ ///
+ /// 调试绘制半径单元数
+ ///
[Export] public int DebugDrawRadiusCells { get; set; } = 20;
+ ///
+ /// 调试日志网格
+ ///
[Export] public bool DebugLogGrid { get; set; }
+ ///
+ /// 环境碰撞掩码
+ ///
[Export] public uint EnvironmentCollisionMask { get; set; } = 1u;
+ ///
+ /// 学生碰撞层
+ ///
[Export] public uint StudentCollisionLayer { get; set; } = 1u << 1;
+ ///
+ /// 准备就绪时调用
+ ///
public override void _Ready()
{
_navigationAgent = GetNodeOrNull("NavigationAgent2D");
@@ -94,6 +269,10 @@ public partial class CampusStudent : CharacterBody2D
_lastPosition = GlobalPosition;
}
+ ///
+ /// 物理处理
+ ///
+ /// 时间间隔
public override void _PhysicsProcess(double delta)
{
_lastDelta = delta;
@@ -212,6 +391,9 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 绘制调试信息
+ ///
public override void _Draw()
{
if (!DebugDrawGrid && !DebugDrawPath) return;
@@ -269,6 +451,11 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 配置巡逻
+ ///
+ /// 巡逻点列表
+ /// 起始索引
public void ConfigurePatrol(List points, int startIndex)
{
_patrolPoints = points ?? new List();
@@ -281,6 +468,9 @@ public partial class CampusStudent : CharacterBody2D
if (_navigationAgent != null) AdvanceTarget();
}
+ ///
+ /// 启用行为控制
+ ///
public void EnableBehaviorControl()
{
_behaviorControlEnabled = true;
@@ -289,6 +479,10 @@ public partial class CampusStudent : CharacterBody2D
_patrolPoints.Clear();
}
+ ///
+ /// 设置行为目标
+ ///
+ /// 目标位置
public void SetBehaviorTarget(Vector2 target)
{
_behaviorControlEnabled = true;
@@ -316,6 +510,9 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 清除行为目标
+ ///
public void ClearBehaviorTarget()
{
_behaviorHasTarget = false;
@@ -329,6 +526,10 @@ public partial class CampusStudent : CharacterBody2D
_gridPath.Clear();
}
+ ///
+ /// 是否已到达行为目标
+ ///
+ /// 到达返回true
public bool HasReachedBehaviorTarget()
{
if (!_behaviorHasTarget) return true;
@@ -344,6 +545,9 @@ public partial class CampusStudent : CharacterBody2D
return _navigationAgent.IsNavigationFinished();
}
+ ///
+ /// 开始玩手机
+ ///
public void StartPhoneIdle()
{
if (_animationPlayer == null || !_animationPlayer.HasAnimation("phone_up")) return;
@@ -354,6 +558,10 @@ public partial class CampusStudent : CharacterBody2D
_animationPlayer.Play("phone_up");
}
+ ///
+ /// 停止玩手机
+ ///
+ /// 是否锁定移动
public void StopPhoneIdle(bool lockMovement = false)
{
if (_animationPlayer == null)
@@ -386,6 +594,10 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 设置导航地图
+ ///
+ /// 地图RID
public void SetNavigationMap(Rid map)
{
// 由校园控制器传入导航地图,供本地边界夹紧使用
@@ -396,6 +608,9 @@ public partial class CampusStudent : CharacterBody2D
_navigationRegion = FindNavigationRegion();
}
+ ///
+ /// 应用随机主题
+ ///
public void ApplyRandomTheme()
{
// 随机替换身体与配件贴图,形成不同主题外观
@@ -410,6 +625,9 @@ public partial class CampusStudent : CharacterBody2D
_smartphone.Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.Phone, Use16X16Sprites));
}
+ ///
+ /// 缓存精灵节点
+ ///
private void CacheSprites()
{
// 缓存子节点引用,避免每帧查找
@@ -421,6 +639,9 @@ public partial class CampusStudent : CharacterBody2D
_smartphone = GetNode("parts/smartphone");
}
+ ///
+ /// 配置碰撞
+ ///
private void ConfigureCollision()
{
// 学生只与环境碰撞,不与其它学生碰撞
@@ -429,6 +650,9 @@ public partial class CampusStudent : CharacterBody2D
_usePhysicsMovement = true;
}
+ ///
+ /// 推进到下一个目标
+ ///
private void AdvanceTarget()
{
if (_patrolPoints.Count == 0 || _navigationAgent == null) return;
@@ -455,6 +679,10 @@ public partial class CampusStudent : CharacterBody2D
_stuckTimer = 0.0f;
}
+ ///
+ /// 计算避让速度时的回调
+ ///
+ /// 安全速度
private void OnVelocityComputed(Vector2 safeVelocity)
{
if (_phoneExitLocked)
@@ -473,6 +701,10 @@ public partial class CampusStudent : CharacterBody2D
UpdateStuckTimer(_lastDelta);
}
+ ///
+ /// 更新卡住计时器
+ ///
+ /// 时间间隔
private void UpdateStuckTimer(double delta)
{
if (StuckRepathSeconds <= 0.0f || !_hasTarget)
@@ -496,6 +728,9 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 重新规划路径到当前目标
+ ///
private void RepathToCurrentTarget()
{
if (!_hasTarget) return;
@@ -516,6 +751,9 @@ public partial class CampusStudent : CharacterBody2D
_navigationAgent.TargetPosition = _currentTarget;
}
+ ///
+ /// 尝试构建挂起的网格路径
+ ///
private void TryBuildPendingGridPath()
{
if (!UseGridPathfinding || !_gridPathPending) return;
@@ -540,11 +778,20 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 导航地图是否准备就绪
+ ///
+ /// 准备就绪返回true
private bool IsNavigationMapReady()
{
return _navigationMap.IsValid && NavigationServer2D.MapGetIterationId(_navigationMap) > 0;
}
+ ///
+ /// 将速度限制在导航网格内
+ ///
+ /// 目标速度
+ /// 限制后的速度
private Vector2 ClampVelocityToNavMesh(Vector2 velocity)
{
if (!IsNavigationMapReady()) return velocity;
@@ -566,6 +813,11 @@ public partial class CampusStudent : CharacterBody2D
return velocity;
}
+ ///
+ /// 将目标点限制在导航网格内
+ ///
+ /// 目标点
+ /// 限制后的目标点
private Vector2 ClampTargetToNavMesh(Vector2 target)
{
if (!IsNavigationMapReady()) return target;
@@ -579,6 +831,10 @@ public partial class CampusStudent : CharacterBody2D
return closest;
}
+ ///
+ /// 应用移动
+ ///
+ /// 时间间隔
private void ApplyMovement(double delta)
{
if (_usePhysicsMovement)
@@ -591,6 +847,10 @@ public partial class CampusStudent : CharacterBody2D
GlobalPosition += Velocity * (float)delta;
}
+ ///
+ /// 更新面朝向动画
+ ///
+ /// 当前速度
private void UpdateFacingAnimation(Vector2 velocity)
{
if (_phoneIdleActive || _phoneExitLocked)
@@ -626,6 +886,9 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 播放闲置动画
+ ///
private void PlayIdleAnimation()
{
if (_phoneIdleActive || _phoneExitLocked)
@@ -650,6 +913,10 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 播放指定动画
+ ///
+ /// 动画名称
private void PlayAnimation(string animationName)
{
if (_animationPlayer == null) return;
@@ -657,6 +924,10 @@ public partial class CampusStudent : CharacterBody2D
if (_animationPlayer.CurrentAnimation != animationName) _animationPlayer.Play(animationName);
}
+ ///
+ /// 动画结束回调
+ ///
+ /// 动画名称
private void OnAnimationFinished(StringName animationName)
{
if (_animationPlayer == null) return;
@@ -677,6 +948,11 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 处理网格路径移动
+ ///
+ /// 时间间隔
+ /// 如果正在移动返回true
private bool ProcessGridPathMovement(double delta)
{
if (_gridPathIndex >= _gridPath.Count)
@@ -730,6 +1006,11 @@ public partial class CampusStudent : CharacterBody2D
return true;
}
+ ///
+ /// 转换为轴向速度
+ ///
+ /// 位移
+ /// 轴向速度
private Vector2 ToAxisVelocity(Vector2 delta)
{
if (Mathf.Abs(delta.X) >= Mathf.Abs(delta.Y))
@@ -740,6 +1021,12 @@ public partial class CampusStudent : CharacterBody2D
return new Vector2(0, Mathf.Sign(delta.Y));
}
+ ///
+ /// 构建网格路径
+ ///
+ /// 起点
+ /// 终点
+ /// 路径点列表
private List BuildGridPath(Vector2 start, Vector2 target)
{
if (!IsNavigationMapReady() || GridCellSize <= 0.0f)
@@ -809,6 +1096,10 @@ public partial class CampusStudent : CharacterBody2D
return SimplifyGridPath(result);
}
+ ///
+ /// 移除直接回头的路径点
+ ///
+ /// 路径
private void RemoveImmediateBacktracks(List path)
{
if (path == null || path.Count < 3) return;
@@ -826,6 +1117,11 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 简化网格路径(移除共线点)
+ ///
+ /// 路径
+ /// 简化后的路径
private List SimplifyGridPath(List path)
{
if (path == null || path.Count < 3) return path;
@@ -863,6 +1159,9 @@ public partial class CampusStudent : CharacterBody2D
return simplified;
}
+ ///
+ /// 确保AStar网格已建立
+ ///
private void EnsureAStarGrid()
{
if (!IsNavigationMapReady()) return;
@@ -916,6 +1215,10 @@ public partial class CampusStudent : CharacterBody2D
}
}
+ ///
+ /// 构建网格区域
+ ///
+ /// 网格区域
private Rect2I BuildGridRegion()
{
var bounds = BuildWorldBounds();
@@ -929,6 +1232,10 @@ public partial class CampusStudent : CharacterBody2D
return new Rect2I(new Vector2I(minX, minY), new Vector2I(sizeX, sizeY));
}
+ ///
+ /// 构建世界边界
+ ///
+ /// 世界边界
private Rect2 BuildWorldBounds()
{
var viewport = GetViewportRect();
@@ -979,6 +1286,11 @@ public partial class CampusStudent : CharacterBody2D
return bounds.Merge(navBounds);
}
+ ///
+ /// 单元格是否在区域内
+ ///
+ /// 单元格
+ /// 如果在区域内返回true
private bool IsCellInRegion(Vector2I cell)
{
return cell.X >= _astarRegion.Position.X
@@ -987,6 +1299,11 @@ public partial class CampusStudent : CharacterBody2D
&& cell.Y < _astarRegion.Position.Y + _astarRegion.Size.Y;
}
+ ///
+ /// 单元格是否在边界内
+ ///
+ /// 单元格
+ /// 如果在边界内返回true
private bool IsCellInBounds(Vector2I cell)
{
if (_astarGrid != null)
@@ -997,6 +1314,11 @@ public partial class CampusStudent : CharacterBody2D
return IsCellInRegion(cell);
}
+ ///
+ /// 世界坐标转网格坐标
+ ///
+ /// 世界坐标
+ /// 网格坐标
private Vector2I WorldToGrid(Vector2 world)
{
var size = Mathf.Max(1.0f, GridCellSize);
@@ -1005,12 +1327,23 @@ public partial class CampusStudent : CharacterBody2D
Mathf.FloorToInt(world.Y / size));
}
+ ///
+ /// 网格坐标转世界坐标
+ ///
+ /// 网格坐标
+ /// 世界坐标
private Vector2 GridToWorld(Vector2I grid)
{
var size = Mathf.Max(1.0f, GridCellSize);
return new Vector2((grid.X + 0.5f) * size, (grid.Y + 0.5f) * size);
}
+ ///
+ /// 查找最近的开放单元格
+ ///
+ /// 起点
+ /// 搜索半径
+ /// 最近的开放单元格
private Vector2I FindNearestOpenCell(Vector2I origin, int radius)
{
if (_astarGrid == null) return origin;
@@ -1039,6 +1372,11 @@ public partial class CampusStudent : CharacterBody2D
return origin;
}
+ ///
+ /// 世界坐标是否可行走
+ ///
+ /// 世界坐标
+ /// 如果可行走返回true
private bool IsWorldWalkable(Vector2 world)
{
if (!IsNavigationMapReady()) return false;
@@ -1046,11 +1384,20 @@ public partial class CampusStudent : CharacterBody2D
return closest.DistanceTo(world) <= GetGridTolerance();
}
+ ///
+ /// 查找导航区域节点
+ ///
+ /// 导航区域
private NavigationRegion2D FindNavigationRegion()
{
return GetTree()?.CurrentScene?.FindChild("NavigationRegion2D", true, false) as NavigationRegion2D;
}
+ ///
+ /// 单元格中心是否可行走
+ ///
+ /// 中心点
+ /// 如果可行走返回true
private bool IsCellWalkable(Vector2 center)
{
if (!IsWorldWalkable(center)) return false;
@@ -1079,16 +1426,12 @@ public partial class CampusStudent : CharacterBody2D
return true;
}
+ ///
+ /// 获取网格容差
+ ///
+ /// 网格容差
private float GetGridTolerance()
{
return Mathf.Max(1.0f, GridWalkableTolerance);
}
-
- private enum FacingDirection
- {
- Up,
- Down,
- Left,
- Right
- }
-}
+}
\ No newline at end of file
diff --git a/scripts/Core/ContentCollectionResource.cs b/scripts/Core/ContentCollectionResource.cs
index f9624ff..dde012a 100644
--- a/scripts/Core/ContentCollectionResource.cs
+++ b/scripts/Core/ContentCollectionResource.cs
@@ -10,8 +10,15 @@ namespace Core;
[GlobalClass]
public partial class ContentCollectionResource : Resource, IContentResourceCollection
{
+ ///
+ /// 资源列表
+ ///
[Export] public Array Items { get; set; } = new();
+ ///
+ /// 获取资源项
+ ///
+ /// 资源项集合
public IEnumerable GetItems()
{
foreach (var item in Items)
@@ -22,5 +29,4 @@ public partial class ContentCollectionResource : Resource, IContentResourceColle
}
}
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/ContentRegistry.cs b/scripts/Core/ContentRegistry.cs
index 2144d80..50db932 100644
--- a/scripts/Core/ContentRegistry.cs
+++ b/scripts/Core/ContentRegistry.cs
@@ -20,27 +20,52 @@ namespace Core;
///
public interface IContentSource
{
+ ///
+ /// 优先级
+ ///
int Priority { get; }
+ ///
+ /// 加载所有指定类型的对象
+ ///
+ /// 对象类型
+ /// 对象集合
IEnumerable LoadAll() where T : class;
}
+///
+/// 内容合并模式
+///
public enum ContentMergeMode
{
- Override,
- KeepFirst
+ Override, // 覆盖
+ KeepFirst // 保留首次
}
+///
+/// 内容注册表
+///
public sealed class ContentRegistry
{
private readonly List _sources = new();
+ ///
+ /// 合并模式
+ ///
public ContentMergeMode MergeMode { get; set; } = ContentMergeMode.Override;
+ ///
+ /// 注册内容源
+ ///
+ /// 内容源
public void RegisterSource(IContentSource source)
{
_sources.Add(source);
_sources.Sort((a, b) => a.Priority.CompareTo(b.Priority));
}
+ ///
+ /// 构建游戏内容数据库
+ ///
+ /// 游戏内容数据库
public GameContentDatabase BuildDatabase()
{
var db = new GameContentDatabase();
@@ -55,6 +80,11 @@ public sealed class ContentRegistry
return db;
}
+ ///
+ /// 从所有源加载指定类型的所有对象
+ ///
+ /// 对象类型
+ /// 对象集合
private IEnumerable LoadAll() where T : class
{
foreach (var source in _sources)
@@ -66,6 +96,13 @@ public sealed class ContentRegistry
}
}
+ ///
+ /// 合并对象到目标字典
+ ///
+ /// 对象类型
+ /// 目标字典
+ /// 对象集合
+ /// ID选择器
private void Merge(Dictionary target, IEnumerable items, Func idSelector) where T : class
{
foreach (var item in items)
@@ -97,14 +134,29 @@ public sealed class ContentRegistry
///
public sealed class ResourceContentSource : IContentSource
{
+ ///
+ /// 优先级
+ ///
public int Priority { get; }
+ ///
+ /// 资源路径列表
+ ///
public List ResourcePaths { get; } = new();
+ ///
+ /// 构造函数
+ ///
+ /// 优先级
public ResourceContentSource(int priority)
{
Priority = priority;
}
+ ///
+ /// 加载所有指定类型的对象
+ ///
+ /// 对象类型
+ /// 对象集合
public IEnumerable LoadAll() where T : class
{
foreach (var path in ResourcePaths)
@@ -127,6 +179,12 @@ public sealed class ResourceContentSource : IContentSource
}
}
+ ///
+ /// 从资源中提取对象
+ ///
+ /// 对象类型
+ /// 资源
+ /// 对象集合
private IEnumerable ExtractResources(Resource resource) where T : class
{
if (resource is IContentResource content)
@@ -163,10 +221,20 @@ public sealed class ResourceContentSource : IContentSource
///
public sealed class JsonContentSource : IContentSource
{
+ ///
+ /// 优先级
+ ///
public int Priority { get; }
+ ///
+ /// 数据路径列表
+ ///
public List DataPaths { get; } = new();
private readonly JsonSerializerOptions _options;
+ ///
+ /// 构造函数
+ ///
+ /// 优先级
public JsonContentSource(int priority)
{
Priority = priority;
@@ -177,6 +245,11 @@ public sealed class JsonContentSource : IContentSource
_options.Converters.Add(new JsonStringEnumConverter());
}
+ ///
+ /// 加载所有指定类型的对象
+ ///
+ /// 对象类型
+ /// 对象集合
public IEnumerable LoadAll() where T : class
{
foreach (var path in DataPaths)
@@ -232,6 +305,11 @@ public sealed class JsonContentSource : IContentSource
}
}
+ ///
+ /// 解析路径
+ ///
+ /// 路径
+ /// 解析后的绝对路径
private string ResolvePath(string path)
{
if (path.StartsWith("res://") || path.StartsWith("user://"))
@@ -242,6 +320,9 @@ public sealed class JsonContentSource : IContentSource
return path;
}
+ ///
+ /// 尝试反序列化列表
+ ///
private bool TryDeserializeList(string json, out List list) where T : class
{
try
@@ -256,6 +337,9 @@ public sealed class JsonContentSource : IContentSource
}
}
+ ///
+ /// 尝试反序列化单个对象
+ ///
private bool TryDeserializeSingle(string json, out T item) where T : class
{
try
@@ -270,6 +354,9 @@ public sealed class JsonContentSource : IContentSource
}
}
+ ///
+ /// 尝试反序列化信封结构
+ ///
private bool TryDeserializeEnvelope(string json, out JsonContentEnvelope envelope) where T : class
{
try
@@ -295,5 +382,4 @@ public sealed class JsonContentSource : IContentSource
public List Items { get; set; }
public T Item { get; set; }
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/ContentResources.cs b/scripts/Core/ContentResources.cs
index d711ddf..e6f3d33 100644
--- a/scripts/Core/ContentResources.cs
+++ b/scripts/Core/ContentResources.cs
@@ -15,13 +15,26 @@ namespace Core;
///
public interface IContentResource
{
+ ///
+ /// 获取定义类型
+ ///
+ /// 类型
Type GetDefinitionType();
+ ///
+ /// 转换为定义对象
+ ///
+ /// 定义对象
object ToDefinition();
}
+///
+/// 资源集合接口
+///
public interface IContentResourceCollection
{
+ ///
+ /// 获取资源项集合
+ ///
+ /// 资源项集合
IEnumerable GetItems();
-}
-
-
+}
\ No newline at end of file
diff --git a/scripts/Core/DisciplineDefinitionResource.cs b/scripts/Core/DisciplineDefinitionResource.cs
index bf78b7c..4264368 100644
--- a/scripts/Core/DisciplineDefinitionResource.cs
+++ b/scripts/Core/DisciplineDefinitionResource.cs
@@ -20,28 +20,81 @@ namespace Core;
public partial class DisciplineDefinitionResource : Resource, IContentResource
{
// --- Header ---
+ ///
+ /// 学科ID
+ ///
[Export] public string Id { get; set; }
+ ///
+ /// 名称键值
+ ///
[Export] public string NameKey { get; set; }
+ ///
+ /// 名称默认值
+ ///
[Export] public string NameFallback { get; set; }
+ ///
+ /// 描述键值
+ ///
[Export] public string DescriptionKey { get; set; }
+ ///
+ /// 描述默认值
+ ///
[Export] public string DescriptionFallback { get; set; }
+ ///
+ /// 图标路径
+ ///
[Export] public string IconPath { get; set; }
+ ///
+ /// 标签列表
+ ///
[Export] public Array Tags { get; set; } = new();
// --- Buff ---
+ ///
+ /// Buff名称键值
+ ///
[Export] public string BuffNameKey { get; set; }
+ ///
+ /// Buff名称默认值
+ ///
[Export] public string BuffNameFallback { get; set; }
+ ///
+ /// Buff描述键值
+ ///
[Export] public string BuffDescriptionKey { get; set; }
+ ///
+ /// Buff描述默认值
+ ///
[Export] public string BuffDescriptionFallback { get; set; }
+ ///
+ /// Buff规则ID列表
+ ///
[Export] public Array BuffRuleIds { get; set; } = new();
// --- Pools ---
+ ///
+ /// 角色池ID列表
+ ///
[Export] public Array RolePoolIds { get; set; } = new();
+ ///
+ /// 物品池ID列表
+ ///
[Export] public Array ItemPoolIds { get; set; } = new();
+ ///
+ /// 任务关键词ID列表
+ ///
[Export] public Array TaskKeywordIds { get; set; } = new();
+ ///
+ /// 获取定义类型
+ ///
+ /// 类型
public Type GetDefinitionType() => typeof(DisciplineDefinition);
+ ///
+ /// 转换为定义对象
+ ///
+ /// 定义对象
public object ToDefinition()
{
var header = new DefinitionHeader
@@ -98,6 +151,11 @@ public partial class DisciplineDefinitionResource : Resource, IContentResource
return definition;
}
+ ///
+ /// 添加范围
+ ///
+ /// 源数组
+ /// 目标列表
private static void AddRange(Array source, List target)
{
foreach (var value in source)
@@ -105,5 +163,4 @@ public partial class DisciplineDefinitionResource : Resource, IContentResource
target.Add(value);
}
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/DomainEvents.cs b/scripts/Core/DomainEvents.cs
index 4ac4547..76eb8a9 100644
--- a/scripts/Core/DomainEvents.cs
+++ b/scripts/Core/DomainEvents.cs
@@ -14,31 +14,57 @@ namespace Core;
///
public readonly struct TaskCompletedEvent
{
+ ///
+ /// 完成的任务
+ ///
public TaskModel Task { get; }
+ ///
+ /// 构造函数
+ ///
+ /// 任务
public TaskCompletedEvent(TaskModel task)
{
Task = task;
}
}
+///
+/// 任务失败事件
+///
public readonly struct TaskFailedEvent
{
+ ///
+ /// 失败的任务
+ ///
public TaskModel Task { get; }
+ ///
+ /// 构造函数
+ ///
+ /// 任务
public TaskFailedEvent(TaskModel task)
{
Task = task;
}
}
+///
+/// 回合结束事件
+///
public readonly struct TurnEndedEvent
{
+ ///
+ /// 结束的回合数
+ ///
public int Turn { get; }
+ ///
+ /// 构造函数
+ ///
+ /// 回合数
public TurnEndedEvent(int turn)
{
Turn = turn;
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/EventBus.cs b/scripts/Core/EventBus.cs
index 2ddc389..ad2e358 100644
--- a/scripts/Core/EventBus.cs
+++ b/scripts/Core/EventBus.cs
@@ -17,6 +17,11 @@ public sealed class DomainEventBus
{
private readonly Dictionary> _handlers = new();
+ ///
+ /// 订阅事件
+ ///
+ /// 事件类型
+ /// 事件处理器
public void Subscribe(Action handler)
{
var type = typeof(T);
@@ -29,6 +34,11 @@ public sealed class DomainEventBus
list.Add(handler);
}
+ ///
+ /// 取消订阅事件
+ ///
+ /// 事件类型
+ /// 事件处理器
public void Unsubscribe(Action handler)
{
var type = typeof(T);
@@ -38,6 +48,11 @@ public sealed class DomainEventBus
}
}
+ ///
+ /// 发布事件
+ ///
+ /// 事件类型
+ /// 事件对象
public void Publish(T evt)
{
var type = typeof(T);
@@ -54,5 +69,4 @@ public sealed class DomainEventBus
}
}
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/GameController.cs b/scripts/Core/GameController.cs
index a8d5089..a247293 100644
--- a/scripts/Core/GameController.cs
+++ b/scripts/Core/GameController.cs
@@ -16,28 +16,40 @@ public sealed class GameController : IController
{
private GameSession _session;
+ ///
+ /// 初始化控制器
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
}
+ ///
+ /// 开始执行阶段
+ ///
public void StartExecution()
{
if (_session.State.Turn.Phase != GamePhase.Planning) return;
_session.State.Turn.Phase = GamePhase.Execution;
}
+ ///
+ /// 结束执行阶段
+ ///
public void EndExecution()
{
if (_session.State.Turn.Phase != GamePhase.Execution) return;
_session.State.Turn.Phase = GamePhase.Review;
}
+ ///
+ /// 开始下一回合
+ ///
public void StartNextTurn()
{
if (_session.State.Turn.Phase != GamePhase.Review) return;
_session.State.Turn.CurrentTurn++;
_session.State.Turn.Phase = GamePhase.Planning;
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/GameSession.cs b/scripts/Core/GameSession.cs
index 4a12208..2282787 100644
--- a/scripts/Core/GameSession.cs
+++ b/scripts/Core/GameSession.cs
@@ -14,12 +14,34 @@ namespace Core;
///
public sealed class GameSession
{
+ ///
+ /// 游戏状态
+ ///
public GameState State { get; }
+ ///
+ /// 游戏内容数据库
+ ///
public GameContentDatabase Content { get; }
+ ///
+ /// 领域事件总线
+ ///
public DomainEventBus Events { get; }
+ ///
+ /// 本地化服务
+ ///
public ILocalizationService Localization { get; }
+ ///
+ /// 游戏系统集合
+ ///
public GameSystems Systems { get; }
+ ///
+ /// 构造游戏会话
+ ///
+ /// 游戏状态
+ /// 内容数据库
+ /// 本地化服务
+ /// 事件总线
public GameSession(GameState state, GameContentDatabase content, ILocalizationService localization, DomainEventBus events)
{
State = state;
@@ -30,6 +52,10 @@ public sealed class GameSession
Systems.Initialize(this);
}
+ ///
+ /// 创建默认游戏会话
+ ///
+ /// 游戏会话实例
public static GameSession CreateDefault()
{
var registry = new ContentRegistry();
@@ -50,9 +76,12 @@ public sealed class GameSession
return new GameSession(new GameState(), content, localization, events);
}
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
Systems.Tick(delta);
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/GameSystems.cs b/scripts/Core/GameSystems.cs
index 3e69452..45a4b87 100644
--- a/scripts/Core/GameSystems.cs
+++ b/scripts/Core/GameSystems.cs
@@ -16,18 +16,48 @@ namespace Core;
///
public interface IGameSystem
{
+ ///
+ /// 初始化系统
+ ///
+ /// 游戏会话
void Initialize(GameSession session);
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
void Tick(float delta);
}
+///
+/// 游戏系统管理器
+///
public sealed class GameSystems
{
+ ///
+ /// 回合系统
+ ///
public TurnSystem Turn { get; } = new();
+ ///
+ /// 任务系统
+ ///
public TaskSystem Task { get; } = new();
+ ///
+ /// 经济系统
+ ///
public EconomySystem Economy { get; } = new();
+ ///
+ /// 羁绊/协同系统
+ ///
public SynergySystem Synergy { get; } = new();
+ ///
+ /// 分配系统
+ ///
public AssignmentSystem Assignment { get; } = new();
+ ///
+ /// 初始化所有系统
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
Turn.Initialize(session);
@@ -37,6 +67,10 @@ public sealed class GameSystems
Assignment.Initialize(session);
}
+ ///
+ /// 更新所有系统
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
Turn.Tick(delta);
@@ -47,32 +81,54 @@ public sealed class GameSystems
}
}
+///
+/// 回合系统
+///
public sealed class TurnSystem : IGameSystem
{
private GameSession _session;
+ ///
+ /// 初始化
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
}
+ ///
+ /// 更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
// 预留:回合推进计时器/阶段切换
}
}
+///
+/// 任务系统
+///
public sealed class TaskSystem : IGameSystem
{
private GameSession _session;
private StatResolver _statResolver;
+ ///
+ /// 初始化
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
_statResolver = new StatResolver(session);
}
+ ///
+ /// 更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
if (_session.State.Turn.Phase != GamePhase.Execution)
@@ -124,6 +180,10 @@ public sealed class TaskSystem : IGameSystem
}
}
+ ///
+ /// 推进任务进度
+ ///
+ /// 时间间隔
private void AdvanceTasks(float delta)
{
var state = _session.State;
@@ -157,6 +217,9 @@ public sealed class TaskSystem : IGameSystem
}
}
+ ///
+ /// 获取单位对任务的贡献
+ ///
private float GetUnitContribution(UnitEntry entry, TaskModel task, TaskDefinition taskDef, float delta)
{
var unit = entry.Unit;
@@ -173,6 +236,9 @@ public sealed class TaskSystem : IGameSystem
return effectivePower;
}
+ ///
+ /// 获取任务基础效率
+ ///
private float GetTaskBasePower(UnitModel unit, TaskKind kind)
{
var academic = _statResolver.GetAttribute(unit, AttributeType.Academic);
@@ -194,6 +260,9 @@ public sealed class TaskSystem : IGameSystem
};
}
+ ///
+ /// 获取状态乘数
+ ///
private float GetStatusMultiplier(UnitEntry entry)
{
var mood = entry.Unit.Statuses.Mood.Normalized;
@@ -213,6 +282,9 @@ public sealed class TaskSystem : IGameSystem
return Math.Clamp(multiplier, 0.3f, 1.2f);
}
+ ///
+ /// 获取角色乘数
+ ///
private float GetRoleMultiplier(UnitModel unit, TaskDefinition taskDef)
{
if (taskDef == null) return 1.0f;
@@ -246,6 +318,9 @@ public sealed class TaskSystem : IGameSystem
return 1.0f;
}
+ ///
+ /// 获取需求乘数
+ ///
private float GetRequirementMultiplier(UnitModel unit, TaskDefinition taskDef)
{
if (taskDef == null) return 1.0f;
@@ -263,6 +338,9 @@ public sealed class TaskSystem : IGameSystem
return multiplier;
}
+ ///
+ /// 获取学科乘数
+ ///
private float GetDisciplineMultiplier(UnitModel unit, TaskDefinition taskDef)
{
if (taskDef == null) return 1.0f;
@@ -280,6 +358,9 @@ public sealed class TaskSystem : IGameSystem
return 0.7f;
}
+ ///
+ /// 获取难度系数
+ ///
private float GetDifficultyScale(TaskDifficulty difficulty)
{
return difficulty switch
@@ -292,12 +373,18 @@ public sealed class TaskSystem : IGameSystem
};
}
+ ///
+ /// 获取任务定义
+ ///
private TaskDefinition GetTaskDefinition(TaskModel task)
{
if (string.IsNullOrWhiteSpace(task.DefinitionId)) return null;
return _session.Content.Tasks.TryGetValue(task.DefinitionId, out var definition) ? definition : null;
}
+ ///
+ /// 构建单位索引
+ ///
private Dictionary BuildUnitIndex()
{
var index = new Dictionary();
@@ -324,6 +411,9 @@ public sealed class TaskSystem : IGameSystem
return index;
}
+ ///
+ /// 追踪贡献
+ ///
private void TrackContribution(UnitEntry entry, TaskModel task, float deltaContribution)
{
if (entry.Student == null) return;
@@ -355,6 +445,9 @@ public sealed class TaskSystem : IGameSystem
}
}
+///
+/// 经济系统
+///
public sealed class EconomySystem : IGameSystem
{
private GameSession _session;
@@ -363,6 +456,10 @@ public sealed class EconomySystem : IGameSystem
private const int PostDocSalary = 1200;
private const int JuniorFacultySalary = 2000;
+ ///
+ /// 初始化
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
@@ -371,11 +468,18 @@ public sealed class EconomySystem : IGameSystem
_session.Events.Subscribe(OnTurnEnded);
}
+ ///
+ /// 更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
// 当前为回合驱动,不在 Tick 中结算
}
+ ///
+ /// 任务完成回调
+ ///
private void OnTaskCompleted(TaskCompletedEvent evt)
{
var task = evt.Task;
@@ -404,6 +508,9 @@ public sealed class EconomySystem : IGameSystem
}
}
+ ///
+ /// 任务失败回调
+ ///
private void OnTaskFailed(TaskFailedEvent evt)
{
var task = evt.Task;
@@ -412,12 +519,18 @@ public sealed class EconomySystem : IGameSystem
_session.State.Economy.Reputation -= penalty;
}
+ ///
+ /// 回合结束回调
+ ///
private void OnTurnEnded(TurnEndedEvent evt)
{
ApplySalaries();
ApplyInterest();
}
+ ///
+ /// 支付薪水
+ ///
private void ApplySalaries()
{
var economy = _session.State.Economy;
@@ -436,6 +549,9 @@ public sealed class EconomySystem : IGameSystem
}
}
+ ///
+ /// 计算利息
+ ///
private void ApplyInterest()
{
var economy = _session.State.Economy;
@@ -446,6 +562,9 @@ public sealed class EconomySystem : IGameSystem
economy.Money += interest;
}
+ ///
+ /// 更新利率
+ ///
private void UpdateInterestRate()
{
var economy = _session.State.Economy;
@@ -456,6 +575,9 @@ public sealed class EconomySystem : IGameSystem
}
}
+ ///
+ /// 添加论文
+ ///
private void AddPaper(PaperRank rank)
{
var inventory = _session.State.Inventory;
@@ -467,6 +589,9 @@ public sealed class EconomySystem : IGameSystem
inventory.PaperCounts[rank] += 1;
}
+ ///
+ /// 添加物品
+ ///
private void AddItem(string itemId, int count)
{
if (string.IsNullOrWhiteSpace(itemId)) return;
@@ -479,6 +604,9 @@ public sealed class EconomySystem : IGameSystem
inventory.ItemCounts[itemId] += count;
}
+ ///
+ /// 根据难度获取论文等级
+ ///
private PaperRank GetPaperRankByDifficulty(TaskDifficulty difficulty)
{
return difficulty switch
@@ -492,20 +620,34 @@ public sealed class EconomySystem : IGameSystem
}
}
+///
+/// 羁绊/协同系统
+///
public sealed class SynergySystem : IGameSystem
{
private GameSession _session;
+ ///
+ /// 初始化
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
}
+ ///
+ /// 更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
RecalculateSynergy();
}
+ ///
+ /// 重新计算协同
+ ///
private void RecalculateSynergy()
{
var state = _session.State.Synergy;
@@ -518,6 +660,9 @@ public sealed class SynergySystem : IGameSystem
ApplySynergyDefinitions(state);
}
+ ///
+ /// 统计单位标签
+ ///
private void CountUnitTags(SynergyState synergy)
{
var roster = _session.State.Roster;
@@ -534,6 +679,9 @@ public sealed class SynergySystem : IGameSystem
}
}
+ ///
+ /// 添加单位标签
+ ///
private void AddUnitTags(SynergyState synergy, UnitModel unit)
{
if (unit == null) return;
@@ -548,6 +696,9 @@ public sealed class SynergySystem : IGameSystem
}
}
+ ///
+ /// 增加堆叠计数
+ ///
private void AddStack(Dictionary stacks, string id)
{
if (string.IsNullOrWhiteSpace(id)) return;
@@ -559,6 +710,9 @@ public sealed class SynergySystem : IGameSystem
stacks[id] += 1;
}
+ ///
+ /// 应用协同定义
+ ///
private void ApplySynergyDefinitions(SynergyState synergy)
{
foreach (var archetype in _session.Content.Archetypes.Values)
@@ -572,6 +726,9 @@ public sealed class SynergySystem : IGameSystem
}
}
+ ///
+ /// 应用协同层级
+ ///
private void ApplySynergyTier(string id, List tiers, Dictionary stacks, SynergyState synergy)
{
if (string.IsNullOrWhiteSpace(id)) return;
@@ -586,6 +743,9 @@ public sealed class SynergySystem : IGameSystem
}
}
+ ///
+ /// 合并修正
+ ///
private void MergeModifiers(ModifierBundle target, ModifierBundle source)
{
if (target == null || source == null) return;
@@ -595,6 +755,9 @@ public sealed class SynergySystem : IGameSystem
target.RuleIds.AddRange(source.RuleIds);
}
+ ///
+ /// 清除修正
+ ///
private void ClearModifiers(ModifierBundle bundle)
{
bundle.AttributeModifiers.Clear();
@@ -604,18 +767,28 @@ public sealed class SynergySystem : IGameSystem
}
}
+///
+/// 分配系统
+///
public sealed class AssignmentSystem : IGameSystem
{
private GameSession _session;
+ ///
+ /// 初始化
+ ///
+ /// 游戏会话
public void Initialize(GameSession session)
{
_session = session;
}
+ ///
+ /// 更新
+ ///
+ /// 帧间隔
public void Tick(float delta)
{
// 预留:人员分配、交接惩罚等
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/LocalizationService.cs b/scripts/Core/LocalizationService.cs
index a8f8ba3..49ae684 100644
--- a/scripts/Core/LocalizationService.cs
+++ b/scripts/Core/LocalizationService.cs
@@ -15,18 +15,43 @@ namespace Core;
///
public interface ILocalizationService
{
+ ///
+ /// 翻译本地化文本对象
+ ///
+ /// 文本对象
+ /// 翻译后的字符串
string Translate(LocalizedText text);
+ ///
+ /// 翻译键值
+ ///
+ /// 键值
+ /// 默认值
+ /// 翻译后的字符串
string Translate(string key, string fallback = null);
}
+///
+/// Godot 本地化服务实现
+///
public sealed class GodotLocalizationService : ILocalizationService
{
+ ///
+ /// 翻译本地化文本对象
+ ///
+ /// 文本对象
+ /// 翻译后的字符串
public string Translate(LocalizedText text)
{
if (text == null) return string.Empty;
return Translate(text.Key, text.Fallback);
}
+ ///
+ /// 翻译键值
+ ///
+ /// 键值
+ /// 默认值
+ /// 翻译后的字符串
public string Translate(string key, string fallback = null)
{
if (string.IsNullOrWhiteSpace(key))
@@ -42,5 +67,4 @@ public sealed class GodotLocalizationService : ILocalizationService
return translated;
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/ModManifest.cs b/scripts/Core/ModManifest.cs
index 96d1a6a..60e1170 100644
--- a/scripts/Core/ModManifest.cs
+++ b/scripts/Core/ModManifest.cs
@@ -14,16 +14,39 @@ namespace Core;
///
public sealed class ModManifest
{
+ ///
+ /// Mod ID
+ ///
public string Id { get; set; }
+ ///
+ /// Mod 名称
+ ///
public string Name { get; set; }
+ ///
+ /// 版本
+ ///
public string Version { get; set; }
+ ///
+ /// 依赖列表
+ ///
public List Dependencies { get; } = new();
+ ///
+ /// 内容路径列表
+ ///
public List ContentPaths { get; } = new();
}
+///
+/// Mod 包
+///
public sealed class ModPackage
{
+ ///
+ /// 清单
+ ///
public ModManifest Manifest { get; set; } = new();
+ ///
+ /// 根路径
+ ///
public string RootPath { get; set; }
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/Mvc.cs b/scripts/Core/Mvc.cs
index db6f81c..b041cf4 100644
--- a/scripts/Core/Mvc.cs
+++ b/scripts/Core/Mvc.cs
@@ -14,26 +14,50 @@ namespace Core;
///
public interface IView
{
+ ///
+ /// 绑定数据模型
+ ///
+ /// 数据模型
void Bind(TModel model);
}
+///
+/// 控制器接口
+///
public interface IController
{
+ ///
+ /// 初始化控制器
+ ///
+ /// 游戏会话
void Initialize(GameSession session);
}
+///
+/// 模型视图基类
+///
+/// 模型类型
public abstract partial class ModelView : Node, IView
{
+ ///
+ /// 数据模型
+ ///
public TModel Model { get; private set; }
+ ///
+ /// 绑定数据模型
+ ///
+ /// 数据模型
public virtual void Bind(TModel model)
{
Model = model;
OnModelBound();
}
+ ///
+ /// 当模型绑定时调用
+ ///
protected virtual void OnModelBound()
{
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Core/StatResolver.cs b/scripts/Core/StatResolver.cs
index d9d0089..8848f7f 100644
--- a/scripts/Core/StatResolver.cs
+++ b/scripts/Core/StatResolver.cs
@@ -17,11 +17,21 @@ public sealed class StatResolver
{
private readonly GameSession _session;
+ ///
+ /// 构造函数
+ ///
+ /// 游戏会话
public StatResolver(GameSession session)
{
_session = session;
}
+ ///
+ /// 获取计算后的属性值
+ ///
+ /// 单位
+ /// 属性类型
+ /// 属性值
public float GetAttribute(UnitModel unit, AttributeType type)
{
var value = GetBaseAttribute(unit, type);
@@ -32,6 +42,12 @@ public sealed class StatResolver
return value;
}
+ ///
+ /// 获取基础属性值
+ ///
+ /// 单位
+ /// 属性类型
+ /// 基础值
private float GetBaseAttribute(UnitModel unit, AttributeType type)
{
return type switch
@@ -46,6 +62,9 @@ public sealed class StatResolver
};
}
+ ///
+ /// 应用学科加成
+ ///
private void ApplyDiscipline(string disciplineId, AttributeType type, ref float value)
{
if (string.IsNullOrWhiteSpace(disciplineId)) return;
@@ -53,6 +72,9 @@ public sealed class StatResolver
ApplyBundle(discipline.Buff?.Modifiers, type, ref value);
}
+ ///
+ /// 应用特质加成
+ ///
private void ApplyTraits(List traitIds, AttributeType type, ref float value)
{
if (traitIds == null || traitIds.Count == 0) return;
@@ -65,6 +87,9 @@ public sealed class StatResolver
}
}
+ ///
+ /// 应用装备加成
+ ///
private void ApplyItems(List itemIds, AttributeType type, ref float value)
{
if (itemIds == null || itemIds.Count == 0) return;
@@ -77,6 +102,9 @@ public sealed class StatResolver
}
}
+ ///
+ /// 应用修正包
+ ///
private void ApplyBundle(ModifierBundle bundle, AttributeType type, ref float value)
{
if (bundle == null) return;
@@ -86,5 +114,4 @@ public sealed class StatResolver
value = (value + modifier.Add) * modifier.Multiplier;
}
}
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Cube.cs b/scripts/Cube.cs
index 9086899..1001e26 100644
--- a/scripts/Cube.cs
+++ b/scripts/Cube.cs
@@ -4,14 +4,20 @@ using System.Collections.Generic;
using System.Linq;
using System.Xml;
+///
+/// 办公格子/图块对象
+///
public partial class Cube : StaticBody2D, ITileDraggable
{
+ // 定义各种家具的占用区域
private static readonly Rect2I tableRect = new(0, 0, 3, 2);
private static readonly Rect2I table2Rect = new(0, -1, 3, 1);
private static readonly Rect2I chairRect = new(1, 1, 1, 2);
private static readonly Rect2I chair2Rect = new(1, -2, 1, 2);
private static readonly Rect2I equipRect = new(0, 0, 3, 2);
private static readonly Rect2I equip2Rect = new(0, -1, 3, 1);
+
+ // 定义桌子的主题映射
private static readonly TileMapping[] tableThemes = {
new(new Vector2I(1, 30), tableRect),
new(new Vector2I(4, 30), tableRect),
@@ -19,6 +25,7 @@ public partial class Cube : StaticBody2D, ITileDraggable
new(new Vector2I(7, 28), tableRect),
new(new Vector2I(10, 28), tableRect),
};
+ // 定义第二种桌子的主题映射
private static readonly TileMapping[] table2Themes = {
new(new Vector2I(1, 31), table2Rect),
new(new Vector2I(4, 31), table2Rect),
@@ -26,12 +33,14 @@ public partial class Cube : StaticBody2D, ITileDraggable
new(new Vector2I(7, 29), table2Rect),
new(new Vector2I(10, 29), table2Rect),
};
+ // 定义椅子的主题映射
private static readonly TileMapping[] chairThemes = {
new(new Vector2I(-1, 7), chairRect),
new(new Vector2I(0, 7), chairRect),
new(new Vector2I(-1, 9), chairRect),
new(new Vector2I(0, 9), chairRect),
};
+ // 定义第二种椅子的主题映射
private static readonly TileMapping[] chair2Themes = {
new(new Vector2I(-1, 10), chair2Rect),
new(new Vector2I(0, 10), chair2Rect),
@@ -39,12 +48,13 @@ public partial class Cube : StaticBody2D, ITileDraggable
new(new Vector2I(0, 12), chair2Rect),
};
+ // 定义设备的主题映射
private static readonly TileMapping[] equipThemes = {
- // one laptop
+ // 一台笔记本电脑
new(new Vector2I(13, 26), equipRect),
- // one laptop with one monitor
+ // 一台笔记本电脑加一台显示器
new(new Vector2I(7, 26), equipRect),
- // one desktop PC
+ // 一台台式机
new(new Dictionary() {
[new Vector2I(0, 0)] = new Vector2I(11, 17),
[new Vector2I(1, 0)] = new Vector2I(8, 32),
@@ -53,30 +63,34 @@ public partial class Cube : StaticBody2D, ITileDraggable
[new Vector2I(1, 1)] = new Vector2I(8, 33),
[new Vector2I(2, 1)] = new Vector2I(9, 33),
}),
- // one desktop PC with one monitors
+ // 一台台式机加一台显示器
new(new Vector2I(7, 32), equipRect),
};
+ // 定义第二种设备的主题映射
private static readonly TileMapping[] equip2Themes = {
- // one laptop
+ // 一台笔记本电脑
new(new Vector2I(13, 31), equip2Rect),
- // one laptop with one monitor
+ // 一台笔记本电脑加一台显示器
new(new Dictionary() {
[new Vector2I(0, -1)] = new Vector2I(13, 32),
[new Vector2I(1, -1)] = new Vector2I(10, 7),
[new Vector2I(2, -1)] = new Vector2I(15, 32),
}),
- // one desktop PC
+ // 一台台式机
new(new Dictionary() {
[new Vector2I(0, -1)] = new Vector2I(13, 32),
[new Vector2I(1, -1)] = new Vector2I(14, 32),
[new Vector2I(2, -1)] = new Vector2I(15, 30),
}),
- // one desktop PC with one monitors
+ // 一台台式机加一台显示器
new(new Vector2I(13, 33), equip2Rect),
};
private bool _draggable;
+ ///
+ /// 是否可拖拽
+ ///
public bool Draggable {
get => _draggable;
set {
@@ -86,10 +100,20 @@ public partial class Cube : StaticBody2D, ITileDraggable
}
private readonly Guid _id = Guid.NewGuid();
+ ///
+ /// 唯一标识符
+ ///
public Guid Id => _id;
+ ///
+ /// 在网格中的位置
+ ///
public Vector2I TilePosition { get; set; } = new Vector2I(5,5);
+
private bool _isCollided = true;
+ ///
+ /// 是否处于碰撞状态(显示红色背景)
+ ///
public bool IsCollided {
get => _isCollided;
set {
@@ -103,9 +127,15 @@ public partial class Cube : StaticBody2D, ITileDraggable
}
}
private static readonly Rect2I tileRect = new(-1, -2, 4, 5);
+ ///
+ /// 占用矩形区域
+ ///
public Rect2I TileRect => tileRect;
private Vector2I _mouseOffset;
+ ///
+ /// 鼠标拖拽偏移
+ ///
public Vector2I MouseOffset => _mouseOffset;
private static readonly ITileDraggable.SpecialTile[] specialTiles = {
@@ -114,15 +144,27 @@ public partial class Cube : StaticBody2D, ITileDraggable
};
+ ///
+ /// 特殊图块(如座位)
+ ///
public ITileDraggable.SpecialTile[] SpecialTiles => specialTiles;
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 节点进入场景树时调用
+ ///
public override void _Ready()
{
RandomChangeTheme();
IsCollided = false;
}
+ ///
+ /// 处理输入事件
+ ///
+ /// 视口
+ /// 输入事件
+ /// 形状索引
public override void _InputEvent(Viewport viewport, InputEvent @event, int shapeIdx)
{
if (@event.IsActionPressed("mouse_left_press")) {
@@ -142,6 +184,10 @@ public partial class Cube : StaticBody2D, ITileDraggable
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧处理
+ ///
+ /// 时间间隔
public override void _Process(double delta)
{
GlobalPosition = TilePosition * 48;
@@ -153,6 +199,10 @@ public partial class Cube : StaticBody2D, ITileDraggable
private int _chair2ThemeIdx;
private int _equipThemeIdx;
private int _equip2ThemeIdx;
+
+ ///
+ /// 随机更换主题样式
+ ///
public void RandomChangeTheme() {
_tableThemeIdx = GD.RandRange(0, tableThemes.Length-1);
_chairThemeIdx = GD.RandRange(0, chairThemes.Length-1);
@@ -177,6 +227,12 @@ public partial class Cube : StaticBody2D, ITileDraggable
new(1,1),
new(2,1),
});
+
+ ///
+ /// 获取指定位置的图块类型
+ ///
+ /// 相对位置
+ /// 图块类型
public Lab.MapNodeType GetTileType(Vector2I pos)
{
GD.Print($"query position of {pos}");
@@ -189,6 +245,11 @@ public partial class Cube : StaticBody2D, ITileDraggable
return Lab.MapNodeType.Walkable;
}
+ ///
+ /// 设置椅子朝向(待实现)
+ ///
+ /// 目标位置
+ /// 索引
public void ChairFaceTo(Vector2I target, int idx) {
if (idx == 0) {
var theme = chairThemes[_chairThemeIdx];
@@ -196,4 +257,4 @@ public partial class Cube : StaticBody2D, ITileDraggable
}
}
-}
\ No newline at end of file
+}
diff --git a/scripts/GameManager.cs b/scripts/GameManager.cs
index 1f0bc57..13d363c 100644
--- a/scripts/GameManager.cs
+++ b/scripts/GameManager.cs
@@ -17,41 +17,105 @@ using Core;
public partial class GameManager : Node
{
///
- /// Indicates if the game is currently in tutorial mode.
+ /// 指示当前是否处于教程模式
///
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");
+ ///
+ /// 最大回合数
+ ///
[Export]
public int MaxTurns = 30;
// --- Global State ---
+
+ ///
+ /// 游戏会话实例
+ ///
public GameSession Session { get; private set; }
+
+ ///
+ /// 当前游戏状态
+ ///
public GameState State => Session?.State;
+
+ ///
+ /// 游戏控制器
+ ///
public GameController Controller { get; private set; }
+ ///
+ /// 当前游戏阶段
+ ///
public GamePhase CurrentPhase => State?.Turn.Phase ?? GamePhase.Planning;
+
+ ///
+ /// 当前回合数
+ ///
public int CurrentTurn => State?.Turn.CurrentTurn ?? 1;
// --- Domain Model ---
+
+ ///
+ /// 导师模型
+ ///
public MentorModel Mentor => State?.Roster.Mentor;
+
+ ///
+ /// 学生列表
+ ///
public List Students => State?.Roster.Students;
+
+ ///
+ /// 当前活动任务列表
+ ///
public List ActiveTasks => State?.Tasks.ActiveTasks;
+
+ ///
+ /// 经济状态
+ ///
public EconomyState Economy => State?.Economy;
// --- 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);
@@ -60,6 +124,9 @@ public partial class GameManager : Node
InitializeGame();
}
+ ///
+ /// 初始化游戏数据
+ ///
private void InitializeGame()
{
Session = GameSession.CreateDefault();
@@ -83,6 +150,10 @@ public partial class GameManager : Node
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧调用
+ ///
+ /// 距离上一帧的时间间隔
public override void _Process(double delta)
{
if (CurrentPhase == GamePhase.Execution)
@@ -157,4 +228,4 @@ public partial class GameManager : Node
GD.Print($"Turn {CurrentTurn} Started. Phase: Planning");
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Helpers.cs b/scripts/Helpers.cs
index b6980cc..7c57ab1 100644
--- a/scripts/Helpers.cs
+++ b/scripts/Helpers.cs
@@ -1,6 +1,15 @@
using Godot;
+///
+/// 辅助工具类
+///
public class H {
+ ///
+ /// 判断矩形是否包含点(包含边界)
+ ///
+ /// 矩形区域
+ /// 点坐标
+ /// 如果点在矩形内(包括边界)则返回true
public static bool RectHasPointInclusive(Rect2I r, Vector2I p) {
if (r.HasPoint(p)) {
return true;
@@ -13,4 +22,4 @@ public class H {
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/scripts/ITileDraggable.cs b/scripts/ITileDraggable.cs
index c37023d..d824dfe 100644
--- a/scripts/ITileDraggable.cs
+++ b/scripts/ITileDraggable.cs
@@ -3,25 +3,73 @@ using System.Diagnostics.SymbolStore;
using System.Dynamic;
using Godot;
+///
+/// 可拖拽图块接口
+///
public interface ITileDraggable {
+ ///
+ /// 图块在网格中的位置
+ ///
Vector2I TilePosition { get; set; }
+
+ ///
+ /// 是否允许拖拽
+ ///
bool Draggable { get; set; }
+
+ ///
+ /// 是否处于碰撞状态(例如位置无效或重叠)
+ ///
bool IsCollided { get; set; }
+
+ ///
+ /// 图块占据的矩形区域(相对于 TilePosition)
+ ///
Rect2I TileRect { get; }
+ ///
+ /// 拖拽时鼠标相对于图块原点的偏移量
+ ///
Vector2I MouseOffset { get; }
+ ///
+ /// 特殊功能图块列表(如座位、交互点等)
+ ///
SpecialTile[] SpecialTiles { get; }
+ ///
+ /// 特殊图块定义
+ ///
class SpecialTile {
+ ///
+ /// 相对位置
+ ///
public readonly Vector2I Position;
+ ///
+ /// 节点类型(如可行走、作为座位等)
+ ///
public readonly Lab.MapNodeType NodeType;
+
+ ///
+ /// 构造特殊图块
+ ///
+ /// 相对位置
+ /// 节点类型
public SpecialTile(Vector2I pos, Lab.MapNodeType node) {
Position = pos;
NodeType = node;
}
}
+
+ ///
+ /// 获取指定相对坐标处的图块类型
+ ///
+ /// 相对坐标
+ /// 地图节点类型
Lab.MapNodeType GetTileType(Vector2I pos);
+ ///
+ /// 唯一标识符
+ ///
Guid Id { get; }
-}
\ No newline at end of file
+}
diff --git a/scripts/Lab.cs b/scripts/Lab.cs
index a1195d6..4077796 100644
--- a/scripts/Lab.cs
+++ b/scripts/Lab.cs
@@ -3,18 +3,26 @@ using System;
using System.Collections.Generic;
using System.Linq;
+///
+/// 实验室场景主控脚本
+///
public partial class Lab : Node2D
{
+ ///
+ /// 地图节点类型标志位
+ ///
[Flags]
public enum MapNodeType
{
- Invalid = 0,
- Walkable = 1,
- Wall = 2,
- Blocker = 4,
- SeatUp = 8,
- SeatDown = 16,
+ Invalid = 0, // 无效
+ Walkable = 1, // 可行走
+ Wall = 2, // 墙壁
+ Blocker = 4, // 阻挡物
+ SeatUp = 8, // 上方座位
+ SeatDown = 16, // 下方座位
}
+
+ // 墙壁矩形区域列表
private static readonly Rect2I[] wallRectangles = {
new(0,0,40,2),
new(0,5,1, 15),
@@ -23,9 +31,15 @@ public partial class Lab : Node2D
};
private readonly Dictionary _furnitureIDs = new();
+ ///
+ /// 家具字典,通过ID索引
+ ///
public Dictionary Furniture => _furnitureIDs;
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
var ticker = GetNode("/root/GameManager/OneSecondTicker");
@@ -57,6 +71,10 @@ public partial class Lab : Node2D
private Label _moneyLabel;
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
switch(GD.RandRange(0,2)) {
@@ -82,12 +100,21 @@ public partial class Lab : Node2D
}
private bool _isDragging;
+
+ ///
+ /// 拾起物品
+ ///
+ /// 目标物品
public void Pickup(ITileDraggable target) {
if (target == null) return;
_isDragging = true;
DraggingTarget = target;
}
+ ///
+ /// 放下物品
+ ///
+ /// 目标物品
public void PutDown(ITileDraggable target) {
if (target == null) return;
_isDragging = false;
@@ -98,6 +125,10 @@ public partial class Lab : Node2D
DraggingTarget = null;
UpdateMap();
}
+
+ ///
+ /// 当前正在拖拽的目标
+ ///
public ITileDraggable DraggingTarget { get; set; }
public const int MapWidth = 40;
@@ -109,6 +140,9 @@ public partial class Lab : Node2D
private TileMapLayer _tileMap;
+ ///
+ /// 更新地图数据
+ ///
public void UpdateMap()
{
for (int i = 0; i < MapWidth; i++) {
@@ -132,8 +166,6 @@ public partial class Lab : Node2D
}
}
-
-
private static bool IsValidPosition(Vector2I pos)
{
int x = pos.X;
@@ -143,6 +175,7 @@ public partial class Lab : Node2D
}
return true;
}
+
private List GetNeighbors(Vector2I pos) {
int x = pos.X;
int y = pos.Y;
@@ -166,6 +199,12 @@ public partial class Lab : Node2D
return neighbor;
}
+ ///
+ /// 获取最短路径
+ ///
+ /// 起点
+ /// 终点
+ /// 路径点列表
public List GetShortestPath(Vector2I start, Vector2I end)
{
for (int j = 0; j < MapHeight; j++) {
@@ -258,19 +297,35 @@ public partial class Lab : Node2D
}
}
+ ///
+ /// 获取指定位置的地图节点类型
+ ///
+ /// 位置
+ /// 节点类型
public MapNodeType GetMapNodeTypeOfPosition(Vector2I pos) {
if (!IsValidPosition(pos)) return MapNodeType.Invalid;
return _blocks[pos.X, pos.Y];
}
+ ///
+ /// 世界坐标转网格坐标
+ ///
+ /// 世界坐标
+ /// 网格坐标
public Vector2I Point2Coord(Vector2 pos) {
return _tileMap.LocalToMap(_tileMap.ToLocal(pos));
}
+ ///
+ /// 获取家具的特殊位置(如座位)
+ ///
+ /// 家具ID
+ /// 索引
+ /// 特殊位置坐标
public Vector2I GetFurSpecialPosition(Guid fId, int idx) {
if (!_furnitureIDs.ContainsKey(fId)) return Vector2I.Zero;
if (idx < 0 || idx > _furnitureIDs[fId].SpecialTiles.Length) return Vector2I.Zero;
return _furnitureIDs[fId].SpecialTiles[idx].Position + _furnitureIDs[fId].TilePosition;
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Loader.cs b/scripts/Loader.cs
index df9f678..024e052 100644
--- a/scripts/Loader.cs
+++ b/scripts/Loader.cs
@@ -2,6 +2,9 @@ using Godot;
using System;
using System.Collections.Generic;
+///
+/// 场景加载器
+///
public partial class Loader : Control
{
private ProgressBar _progressBar;
@@ -12,6 +15,9 @@ public partial class Loader : Control
};
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
_progressBar = GetNode("ProgressBar");
@@ -31,6 +37,10 @@ public partial class Loader : Control
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
Godot.Collections.Array progress = new();
@@ -53,4 +63,4 @@ public partial class Loader : Control
break;
}
}
-}
\ No newline at end of file
+}
diff --git a/scripts/LogoScene.cs b/scripts/LogoScene.cs
index c08afa7..372e599 100644
--- a/scripts/LogoScene.cs
+++ b/scripts/LogoScene.cs
@@ -1,15 +1,25 @@
using Godot;
using System;
+///
+/// Logo场景
+///
public partial class LogoScene : Node2D
{
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready() {
GetNode("AnimationPlayer").AnimationFinished += OnAnimationPlayerAnimationFinished;
}
+ ///
+ /// 动画播放结束回调
+ ///
+ /// 动画名称
public void OnAnimationPlayerAnimationFinished(StringName animationName)
{
GD.Print("FFF");
GetTree().ChangeSceneToFile("res://scenes/loader.tscn");
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/CoreIds.cs b/scripts/Models/CoreIds.cs
index 75f603e..230c9c6 100644
--- a/scripts/Models/CoreIds.cs
+++ b/scripts/Models/CoreIds.cs
@@ -12,44 +12,142 @@ namespace Models;
///
public static class CoreIds
{
+ ///
+ /// 默认命名空间
+ ///
public const string Namespace = "core";
// Disciplines
+ ///
+ /// 生物学
+ ///
public const string DisciplineBiology = "core:discipline_biology";
+ ///
+ /// 化学
+ ///
public const string DisciplineChemistry = "core:discipline_chemistry";
+ ///
+ /// 环境科学
+ ///
public const string DisciplineEnvironment = "core:discipline_environment";
+ ///
+ /// 材料学
+ ///
public const string DisciplineMaterials = "core:discipline_materials";
+ ///
+ /// 医学
+ ///
public const string DisciplineMedicine = "core:discipline_medicine";
+ ///
+ /// 计算机
+ ///
public const string DisciplineComputer = "core:discipline_computer";
+ ///
+ /// 数学
+ ///
public const string DisciplineMath = "core:discipline_math";
+ ///
+ /// 物理学
+ ///
public const string DisciplinePhysics = "core:discipline_physics";
+ ///
+ /// 机械工程
+ ///
public const string DisciplineMechanical = "core:discipline_mechanical";
+ ///
+ /// 哲学
+ ///
public const string DisciplinePhilosophy = "core:discipline_philosophy";
+ ///
+ /// 经济学
+ ///
public const string DisciplineEconomics = "core:discipline_economics";
+ ///
+ /// 法学
+ ///
public const string DisciplineLaw = "core:discipline_law";
+ ///
+ /// 文学
+ ///
public const string DisciplineLiterature = "core:discipline_literature";
+ ///
+ /// 农学
+ ///
public const string DisciplineAgriculture = "core:discipline_agriculture";
+ ///
+ /// 管理学
+ ///
public const string DisciplineManagement = "core:discipline_management";
+ ///
+ /// 艺术
+ ///
public const string DisciplineArt = "core:discipline_art";
// Archetypes
+ ///
+ /// 卷王
+ ///
public const string ArchetypeGrinder = "core:archetype_grinder";
+ ///
+ /// 摸鱼
+ ///
public const string ArchetypeSlacker = "core:archetype_slacker";
+ ///
+ /// 精英
+ ///
public const string ArchetypeElite = "core:archetype_elite";
+ ///
+ /// 天才
+ ///
public const string ArchetypeProdigy = "core:archetype_prodigy";
+ ///
+ /// 吉祥物
+ ///
public const string ArchetypeMascot = "core:archetype_mascot";
// Roles
+ ///
+ /// 码农
+ ///
public const string RoleCoder = "core:role_coder";
+ ///
+ /// 写手
+ ///
public const string RoleWriter = "core:role_writer";
+ ///
+ /// 实验员
+ ///
public const string RoleLabRat = "core:role_lab_rat";
+ ///
+ /// 讲演者
+ ///
public const string RolePresenter = "core:role_presenter";
+ ///
+ /// 记录员
+ ///
public const string RoleScribe = "core:role_scribe";
+ ///
+ /// 辩论者
+ ///
public const string RoleOrator = "core:role_orator";
+ ///
+ /// 管家
+ ///
public const string RoleSteward = "core:role_steward";
+ ///
+ /// 炼金术士
+ ///
public const string RoleAlchemist = "core:role_alchemist";
+ ///
+ /// 极客
+ ///
public const string RoleGeek = "core:role_geek";
+ ///
+ /// 勘测员
+ ///
public const string RoleSurveyor = "core:role_surveyor";
+ ///
+ /// 思考者
+ ///
public const string RoleThinker = "core:role_thinker";
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/DefinitionSupport.cs b/scripts/Models/DefinitionSupport.cs
index fb95a65..0196692 100644
--- a/scripts/Models/DefinitionSupport.cs
+++ b/scripts/Models/DefinitionSupport.cs
@@ -17,16 +17,36 @@ namespace Models;
///
public sealed class LocalizedText
{
+ ///
+ /// 键值
+ ///
public string Key { get; set; }
+ ///
+ /// 默认值
+ ///
public string Fallback { get; set; }
}
public sealed class DefinitionHeader
{
+ ///
+ /// 定义ID
+ ///
public string Id { get; set; }
+ ///
+ /// 名称
+ ///
public LocalizedText Name { get; set; } = new();
+ ///
+ /// 描述
+ ///
public LocalizedText Description { get; set; } = new();
+ ///
+ /// 图标路径
+ ///
public string IconPath { get; set; }
+ ///
+ /// 标签列表
+ ///
public List Tags { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/DisciplineDefinitions.cs b/scripts/Models/DisciplineDefinitions.cs
index 900aa28..0236c68 100644
--- a/scripts/Models/DisciplineDefinitions.cs
+++ b/scripts/Models/DisciplineDefinitions.cs
@@ -14,18 +14,44 @@ namespace Models;
///
public sealed class DisciplineDefinition
{
+ ///
+ /// 基础头部信息
+ ///
public DefinitionHeader Header { get; set; } = new();
+ ///
+ /// 学科Buff
+ ///
public DisciplineBuff Buff { get; set; } = new();
+ ///
+ /// 角色池ID列表
+ ///
public List RolePoolIds { get; } = new();
+ ///
+ /// 物品池ID列表
+ ///
public List ItemPoolIds { get; } = new();
+ ///
+ /// 任务关键词ID列表
+ ///
public List TaskKeywordIds { get; } = new();
}
+///
+/// 学科Buff定义
+///
public sealed class DisciplineBuff
{
+ ///
+ /// 名称
+ ///
public LocalizedText Name { get; set; } = new();
+ ///
+ /// 描述
+ ///
public LocalizedText Description { get; set; } = new();
+ ///
+ /// 修正包
+ ///
public ModifierBundle Modifiers { get; set; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/DomainEnums.cs b/scripts/Models/DomainEnums.cs
index dc54745..28078c4 100644
--- a/scripts/Models/DomainEnums.cs
+++ b/scripts/Models/DomainEnums.cs
@@ -12,32 +12,31 @@ namespace Models;
///
public enum AttributeType
{
- Academic,
- Engineering,
- Writing,
- Financial,
- Social,
- Activation
+ Academic, // 学术
+ Engineering, // 工程
+ Writing, // 写作
+ Financial, // 财务
+ Social, // 社交
+ Activation // 活跃/执行
}
public enum ResourceType
{
- Money,
- Reputation,
- ResearchPoints,
- Paper,
- Inspiration,
- Time
+ Money, // 金钱
+ Reputation, // 声望
+ ResearchPoints, // 科研点
+ Paper, // 论文
+ Inspiration, // 灵感
+ Time // 时间
}
public enum StatusType
{
- Stress,
- Sanity,
- Mood,
- Stamina,
- Loyalty,
- Energy,
- Health
-}
-
+ Stress, // 压力
+ Sanity, // 理智
+ Mood, // 心情
+ Stamina, // 体力
+ Loyalty, // 忠诚度
+ Energy, // 精力
+ Health // 健康
+}
\ No newline at end of file
diff --git a/scripts/Models/GameContentDatabase.cs b/scripts/Models/GameContentDatabase.cs
index 608ff73..a7adb83 100644
--- a/scripts/Models/GameContentDatabase.cs
+++ b/scripts/Models/GameContentDatabase.cs
@@ -14,13 +14,36 @@ namespace Models;
///
public sealed class GameContentDatabase
{
+ ///
+ /// 学科定义字典
+ ///
public Dictionary Disciplines { get; } = new();
+ ///
+ /// 原型定义字典
+ ///
public Dictionary Archetypes { get; } = new();
+ ///
+ /// 角色定义字典
+ ///
public Dictionary Roles { get; } = new();
+ ///
+ /// 特质定义字典
+ ///
public Dictionary Traits { get; } = new();
+ ///
+ /// 任务定义字典
+ ///
public Dictionary Tasks { get; } = new();
+ ///
+ /// 物品定义字典
+ ///
public Dictionary Items { get; } = new();
+ ///
+ /// 论文定义字典
+ ///
public Dictionary Papers { get; } = new();
+ ///
+ /// 肉鸽天赋定义字典
+ ///
public Dictionary RoguelitePerks { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/GameState.cs b/scripts/Models/GameState.cs
index bebf3a0..12b1bbe 100644
--- a/scripts/Models/GameState.cs
+++ b/scripts/Models/GameState.cs
@@ -17,69 +17,179 @@ namespace Models;
///
public sealed class GameState
{
+ ///
+ /// 回合状态
+ ///
public TurnState Turn { get; } = new();
+ ///
+ /// 经济状态
+ ///
public EconomyState Economy { get; } = new();
+ ///
+ /// 人员状态
+ ///
public RosterState Roster { get; } = new();
+ ///
+ /// 任务状态
+ ///
public TaskState Tasks { get; } = new();
+ ///
+ /// 库存状态
+ ///
public InventoryState Inventory { get; } = new();
+ ///
+ /// 协同状态
+ ///
public SynergyState Synergy { get; } = new();
+ ///
+ /// 肉鸽状态
+ ///
public RogueliteState Roguelite { get; } = new();
}
+///
+/// 游戏阶段
+///
public enum GamePhase
{
- Planning,
- Execution,
- Review
+ Planning, // 筹备阶段
+ Execution, // 执行阶段
+ Review // 结算阶段
}
+///
+/// 回合状态数据
+///
public sealed class TurnState
{
+ ///
+ /// 当前回合
+ ///
public int CurrentTurn { get; set; } = 1;
+ ///
+ /// 最大回合
+ ///
public int MaxTurns { get; set; } = 30;
+ ///
+ /// 当前阶段
+ ///
public GamePhase Phase { get; set; } = GamePhase.Planning;
}
+///
+/// 经济状态数据
+///
public sealed class EconomyState
{
+ ///
+ /// 资金
+ ///
public int Money { get; set; } = 50000;
+ ///
+ /// 声望
+ ///
public int Reputation { get; set; }
+ ///
+ /// 科研点数
+ ///
public int ResearchPoints { get; set; }
+ ///
+ /// 利率
+ ///
public float InterestRate { get; set; } = 0.0f;
}
+///
+/// 人员状态数据
+///
public sealed class RosterState
{
+ ///
+ /// 导师模型
+ ///
public MentorModel Mentor { get; set; } = new("Player");
+ ///
+ /// 学生列表
+ ///
public List Students { get; } = new();
+ ///
+ /// 职工列表
+ ///
public List Staffs { get; } = new();
}
+///
+/// 任务状态数据
+///
public sealed class TaskState
{
+ ///
+ /// 活动任务列表
+ ///
public List ActiveTasks { get; } = new();
+ ///
+ /// 已完成任务列表
+ ///
public List CompletedTasks { get; } = new();
+ ///
+ /// 失败任务列表
+ ///
public List FailedTasks { get; } = new();
}
+///
+/// 库存状态数据
+///
public sealed class InventoryState
{
+ ///
+ /// 物品计数
+ ///
public Dictionary ItemCounts { get; } = new();
+ ///
+ /// 论文计数
+ ///
public Dictionary PaperCounts { get; } = new();
}
+///
+/// 协同状态数据
+///
public sealed class SynergyState
{
+ ///
+ /// 原型堆叠数
+ ///
public Dictionary ArchetypeStacks { get; } = new();
+ ///
+ /// 角色堆叠数
+ ///
public Dictionary RoleStacks { get; } = new();
+ ///
+ /// 激活的协同ID列表
+ ///
public List ActiveSynergyIds { get; } = new();
+ ///
+ /// 激活的修正包
+ ///
public ModifierBundle ActiveModifiers { get; } = new();
}
+///
+/// 肉鸽状态数据
+///
public sealed class RogueliteState
{
+ ///
+ /// 校友卡ID列表
+ ///
public List AlumniCardIds { get; } = new();
+ ///
+ /// 遗产解锁ID列表
+ ///
public List LegacyUnlockIds { get; } = new();
+ ///
+ /// 头衔保留等级
+ ///
public int TitleRetentionLevel { get; set; }
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/ItemDefinitions.cs b/scripts/Models/ItemDefinitions.cs
index 6eeb83f..e258c8a 100644
--- a/scripts/Models/ItemDefinitions.cs
+++ b/scripts/Models/ItemDefinitions.cs
@@ -14,29 +14,29 @@ namespace Models;
///
public enum ItemCategory
{
- Facility,
- Equipment,
- Consumable
+ Facility, // 设施
+ Equipment, // 装备
+ Consumable // 消耗品
}
public enum FacilityPlacement
{
- Lab,
- ServerRoom,
- Admin,
- Library,
- RestArea,
- Field,
- Global
+ Lab, // 实验室
+ ServerRoom, // 机房
+ Admin, // 行政区
+ Library, // 图书馆
+ RestArea, // 休息区
+ Field, // 场地
+ Global // 全局
}
public enum EquipmentSlot
{
- Tool,
- Accessory,
- Body,
- Head,
- Hand
+ Tool, // 工具
+ Accessory, // 饰品
+ Body, // 身体
+ Head, // 头部
+ Hand // 手部
}
public sealed class ItemDefinition
@@ -55,5 +55,4 @@ public sealed class ItemEffect
{
public ModifierBundle Modifiers { get; set; } = new();
public List RuleIds { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/MentorModel.cs b/scripts/Models/MentorModel.cs
index c84b24b..49b5c0d 100644
--- a/scripts/Models/MentorModel.cs
+++ b/scripts/Models/MentorModel.cs
@@ -14,22 +14,41 @@ namespace Models;
///
public sealed class MentorModel
{
+ ///
+ /// 导师模式
+ ///
public enum MentorModeType
{
- Worker,
- Manager
+ Worker, // 打工人
+ Manager // 管理者
}
+ ///
+ /// 核心单位数据
+ ///
public UnitModel Core { get; }
+ ///
+ /// 导师特有资源
+ ///
public MentorResources Resources { get; }
+ ///
+ /// 当前模式
+ ///
public MentorModeType Mode { get; set; } = MentorModeType.Worker;
+ ///
+ /// 名字(便捷访问)
+ ///
public string Name
{
get => Core.Name;
set => Core.Name = value;
}
+ ///
+ /// 构造函数
+ ///
+ /// 名字
public MentorModel(string name)
{
Core = new UnitModel(name);
@@ -42,10 +61,13 @@ public sealed class MentorModel
///
public sealed class MentorResources
{
+ ///
+ /// 精力值
+ ///
public StatusValue Energy { get; set; }
public MentorResources()
{
Energy = new StatusValue(100, 100, 0);
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/Modifiers.cs b/scripts/Models/Modifiers.cs
index 44485a0..8d35270 100644
--- a/scripts/Models/Modifiers.cs
+++ b/scripts/Models/Modifiers.cs
@@ -14,30 +14,68 @@ namespace Models;
///
public sealed class AttributeModifier
{
+ ///
+ /// 属性类型
+ ///
public AttributeType Type { get; set; }
+ ///
+ /// 加值
+ ///
public float Add { get; set; }
+ ///
+ /// 乘数
+ ///
public float Multiplier { get; set; } = 1.0f;
}
public sealed class StatusModifier
{
+ ///
+ /// 状态类型
+ ///
public StatusType Type { get; set; }
+ ///
+ /// 加值
+ ///
public float Add { get; set; }
+ ///
+ /// 乘数
+ ///
public float Multiplier { get; set; } = 1.0f;
}
public sealed class ResourceModifier
{
+ ///
+ /// 资源类型
+ ///
public ResourceType Type { get; set; }
+ ///
+ /// 加值
+ ///
public int Add { get; set; }
+ ///
+ /// 乘数
+ ///
public float Multiplier { get; set; } = 1.0f;
}
public sealed class ModifierBundle
{
+ ///
+ /// 属性修正列表
+ ///
public List AttributeModifiers { get; } = new();
+ ///
+ /// 状态修正列表
+ ///
public List StatusModifiers { get; } = new();
+ ///
+ /// 资源修正列表
+ ///
public List ResourceModifiers { get; } = new();
+ ///
+ /// 规则ID列表
+ ///
public List RuleIds { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/PaperDefinitions.cs b/scripts/Models/PaperDefinitions.cs
index 3b1a66a..4a086ab 100644
--- a/scripts/Models/PaperDefinitions.cs
+++ b/scripts/Models/PaperDefinitions.cs
@@ -14,5 +14,4 @@ public sealed class PaperDefinition
{
public DefinitionHeader Header { get; set; } = new();
public PaperRank Rank { get; set; }
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/PropertyValue.cs b/scripts/Models/PropertyValue.cs
index b4a128b..7557335 100644
--- a/scripts/Models/PropertyValue.cs
+++ b/scripts/Models/PropertyValue.cs
@@ -20,17 +20,32 @@ public sealed class PropertyValue
public const float DefaultMin = 0f;
public const float DefaultMax = 100f;
+ ///
+ /// 最小值
+ ///
public float Min { get; }
+ ///
+ /// 最大值
+ ///
public float Max { get; }
private float _value;
+ ///
+ /// 当前值(自动限制在 Min/Max 范围内)
+ ///
public float Value
{
get => _value;
set => _value = Clamp(value, Min, Max);
}
+ ///
+ /// 构造函数
+ ///
+ /// 初始值
+ /// 最小值
+ /// 最大值
public PropertyValue(float value = 0, float min = DefaultMin, float max = DefaultMax)
{
if (max < min)
@@ -44,13 +59,26 @@ public sealed class PropertyValue
Value = value;
}
+ ///
+ /// 构造函数(整数)
+ ///
+ /// 初始值
+ /// 最小值
+ /// 最大值
public PropertyValue(int value, float min = DefaultMin, float max = DefaultMax)
: this((float)value, min, max)
{
}
+ ///
+ /// 获取显示的整数值
+ ///
+ /// 整数值
public int DisplayInt() => (int)_value;
+ ///
+ /// 获取归一化值 (0.0 - 1.0)
+ ///
public float Normalized
{
get
@@ -60,10 +88,22 @@ public sealed class PropertyValue
}
}
+ ///
+ /// 克隆
+ ///
+ /// 新实例
public PropertyValue Clone() => new(Value, Min, Max);
+ ///
+ /// 增加值
+ ///
+ /// 增量
public void Add(float delta) => Value += delta;
+ ///
+ /// 减少值
+ ///
+ /// 减量
public void Subtract(float delta) => Value -= delta;
public override string ToString() => DisplayInt().ToString();
@@ -128,4 +168,4 @@ public sealed class PropertyValue
if (value > max) return max;
return value;
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/RogueliteDefinitions.cs b/scripts/Models/RogueliteDefinitions.cs
index 160257a..3827058 100644
--- a/scripts/Models/RogueliteDefinitions.cs
+++ b/scripts/Models/RogueliteDefinitions.cs
@@ -12,16 +12,27 @@ namespace Models;
///
public enum RoguelitePerkType
{
- AlumniCard,
- LegacyProgress,
- TitleRetention
+ AlumniCard, // 校友卡
+ LegacyProgress, // 遗产进度
+ TitleRetention // 头衔保留
}
public sealed class RoguelitePerkDefinition
{
+ ///
+ /// 基础头部信息
+ ///
public DefinitionHeader Header { get; set; } = new();
+ ///
+ /// 天赋类型
+ ///
public RoguelitePerkType Type { get; set; }
+ ///
+ /// 修正包
+ ///
public ModifierBundle Modifiers { get; set; } = new();
+ ///
+ /// 最大等级
+ ///
public int MaxLevel { get; set; } = 1;
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/StaffModel.cs b/scripts/Models/StaffModel.cs
index f7e737f..d92c7e9 100644
--- a/scripts/Models/StaffModel.cs
+++ b/scripts/Models/StaffModel.cs
@@ -14,22 +14,43 @@ namespace Models;
///
public sealed class StaffModel
{
+ ///
+ /// 职员类型
+ ///
public enum StaffType
{
- PostDoc,
- JuniorFaculty
+ PostDoc, // 博士后
+ JuniorFaculty // 青年教师
}
+ ///
+ /// 核心单位数据
+ ///
public UnitModel Core { get; }
+ ///
+ /// 职员类型
+ ///
public StaffType Type { get; private set; }
+ ///
+ /// 动机数据
+ ///
public StaffMotivation Motivation { get; }
+ ///
+ /// 名字(便捷访问)
+ ///
public string Name
{
get => Core.Name;
set => Core.Name = value;
}
+ ///
+ /// 构造函数
+ ///
+ /// 名字
+ /// 类型
+ /// 随机数生成器
public StaffModel(string name, StaffType type, Random random = null)
{
Core = new UnitModel(name, random);
@@ -38,10 +59,21 @@ public sealed class StaffModel
}
}
+///
+/// 职员动机组件
+///
public sealed class StaffMotivation
{
+ ///
+ /// 野心
+ ///
public StatusValue Ambition { get; set; } = new(50, 100, 0);
+ ///
+ /// 忠诚度
+ ///
public StatusValue Loyalty { get; set; } = new(70, 100, 0);
+ ///
+ /// 合同剩余回合
+ ///
public StatusValue ContractTurns { get; set; } = new(6, 12, 0);
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/StatusValue.cs b/scripts/Models/StatusValue.cs
index 1c0b677..dc7a0ad 100644
--- a/scripts/Models/StatusValue.cs
+++ b/scripts/Models/StatusValue.cs
@@ -19,9 +19,18 @@ public sealed class StatusValue
{
private PropertyValue _current;
+ ///
+ /// 达到上限事件
+ ///
public event Action OnUpperThresholdReached;
+ ///
+ /// 达到下限事件
+ ///
public event Action OnLowerThresholdReached;
+ ///
+ /// 当前值
+ ///
public PropertyValue Current
{
get => _current;
@@ -32,9 +41,18 @@ public sealed class StatusValue
}
}
+ ///
+ /// 上限阈值
+ ///
public float UpperThreshold { get; set; }
+ ///
+ /// 下限阈值
+ ///
public float LowerThreshold { get; set; }
+ ///
+ /// 构造函数(整数)
+ ///
public StatusValue(int current = 0, int upper = 100, int lower = 0)
{
_current = new PropertyValue(current, lower, upper);
@@ -42,6 +60,9 @@ public sealed class StatusValue
LowerThreshold = lower;
}
+ ///
+ /// 构造函数(浮点数)
+ ///
public StatusValue(float current, float upper, float lower)
{
_current = new PropertyValue(current, lower, upper);
@@ -49,6 +70,9 @@ public sealed class StatusValue
LowerThreshold = lower;
}
+ ///
+ /// 构造函数(PropertyValue)
+ ///
public StatusValue(PropertyValue current, float upperThreshold, float lowerThreshold)
{
_current = current ?? new PropertyValue(0);
@@ -70,15 +94,21 @@ public sealed class StatusValue
}
}
+ ///
+ /// 增加值
+ ///
public void Add(float value)
{
_current.Add(value);
CheckThresholds();
}
+ ///
+ /// 减少值
+ ///
public void Subtract(float value)
{
_current.Subtract(value);
CheckThresholds();
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/StudentModel.cs b/scripts/Models/StudentModel.cs
index ca749a7..f7faa9c 100644
--- a/scripts/Models/StudentModel.cs
+++ b/scripts/Models/StudentModel.cs
@@ -18,25 +18,51 @@ namespace Models;
///
public sealed class StudentModel
{
+ ///
+ /// 学生类型
+ ///
public enum StudentType
{
- MasterCandidate,
- DoctorCandidate
+ MasterCandidate, // 硕士生
+ DoctorCandidate // 博士生
}
+ ///
+ /// 核心单位数据
+ ///
public UnitModel Core { get; }
+ ///
+ /// 学生类型
+ ///
public StudentType Type { get; private set; }
+ ///
+ /// 进度数据
+ ///
public StudentProgress Progress { get; }
+ ///
+ /// 贡献记录
+ ///
public StudentContributions Contributions { get; }
+ ///
+ /// 名字(便捷访问)
+ ///
public string Name
{
get => Core.Name;
set => Core.Name = value;
}
+ ///
+ /// 特质列表(便捷访问)
+ ///
public List Traits => Core.Tags.TraitIds;
+ ///
+ /// 构造函数
+ ///
+ /// 名字
+ /// 随机数生成器
public StudentModel(string name, Random random = null)
{
var rng = random ?? Random.Shared;
@@ -52,8 +78,17 @@ public sealed class StudentModel
///
public sealed class StudentProgress
{
+ ///
+ /// 体力
+ ///
public StatusValue Stamina { get; set; }
+ ///
+ /// 忠诚度
+ ///
public StatusValue Loyalty { get; set; }
+ ///
+ /// 年级
+ ///
public PropertyValue Grade { get; set; }
public StudentProgress(StudentModel.StudentType type)
@@ -70,5 +105,8 @@ public sealed class StudentProgress
///
public sealed class StudentContributions
{
+ ///
+ /// 按任务ID索引的贡献值
+ ///
public Dictionary ByTask { get; } = new();
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/SynergyDefinitions.cs b/scripts/Models/SynergyDefinitions.cs
index 0d475e2..e5d635b 100644
--- a/scripts/Models/SynergyDefinitions.cs
+++ b/scripts/Models/SynergyDefinitions.cs
@@ -14,30 +14,62 @@ namespace Models;
///
public sealed class ArchetypeDefinition
{
+ ///
+ /// 基础头部信息
+ ///
public DefinitionHeader Header { get; set; } = new();
+ ///
+ /// 羁绊层级列表
+ ///
public List Tiers { get; } = new();
}
public sealed class RoleDefinition
{
+ ///
+ /// 基础头部信息
+ ///
public DefinitionHeader Header { get; set; } = new();
+ ///
+ /// 羁绊层级列表
+ ///
public List Tiers { get; } = new();
// 如果是学科限定角色(如炼金术士/极客),在这里配置允许的学科 Id。
+ ///
+ /// 允许的学科ID列表
+ ///
public List AllowedDisciplineIds { get; } = new();
}
public sealed class TraitDefinition
{
+ ///
+ /// 基础头部信息
+ ///
public DefinitionHeader Header { get; set; } = new();
+ ///
+ /// 修正包
+ ///
public ModifierBundle Modifiers { get; set; } = new();
+ ///
+ /// 规则ID列表
+ ///
public List RuleIds { get; } = new();
}
public sealed class SynergyTier
{
+ ///
+ /// 需求数量
+ ///
public int RequiredCount { get; set; }
+ ///
+ /// 修正包
+ ///
public ModifierBundle Modifiers { get; set; } = new();
+ ///
+ /// 规则ID列表
+ ///
public List RuleIds { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/Task.cs b/scripts/Models/Task.cs
index 5671b3a..4cc33ed 100644
--- a/scripts/Models/Task.cs
+++ b/scripts/Models/Task.cs
@@ -77,4 +77,4 @@ public sealed class TaskRewardSnapshot
public int Reputation { get; set; }
public List PaperIds { get; } = new();
public List ItemIds { get; set; }
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/TaskDefinitions.cs b/scripts/Models/TaskDefinitions.cs
index 9105193..a5f5133 100644
--- a/scripts/Models/TaskDefinitions.cs
+++ b/scripts/Models/TaskDefinitions.cs
@@ -33,10 +33,10 @@ public enum TaskKind
public enum TaskDifficulty
{
- Water,
- Standard,
- Hardcore,
- BlackBox
+ Water, // 水
+ Standard, // 标准
+ Hardcore, // 硬核
+ BlackBox // 黑箱
}
public enum PaperRank
@@ -97,5 +97,4 @@ public sealed class TaskRewards
public List PaperIds { get; } = new();
public List ItemIds { get; } = new();
public List BuffIds { get; } = new();
-}
-
+}
\ No newline at end of file
diff --git a/scripts/Models/UnitComponents.cs b/scripts/Models/UnitComponents.cs
index 5c17418..23a1777 100644
--- a/scripts/Models/UnitComponents.cs
+++ b/scripts/Models/UnitComponents.cs
@@ -18,6 +18,9 @@ namespace Models;
///
public static class UnitComponents
{
+ ///
+ /// 网格位置组件
+ ///
public readonly struct GridPosition
{
public int X { get; }
@@ -32,6 +35,9 @@ public static class UnitComponents
public static GridPosition Zero => new(0, 0);
}
+ ///
+ /// 单位身份组件
+ ///
public sealed class UnitIdentity
{
public Guid Id { get; } = Guid.NewGuid();
@@ -45,6 +51,9 @@ public static class UnitComponents
}
}
+ ///
+ /// 单位属性组件
+ ///
public sealed class UnitAttributes
{
public PropertyValue Academic { get; set; }
@@ -66,6 +75,9 @@ public static class UnitComponents
}
}
+ ///
+ /// 单位状态组件
+ ///
public sealed class UnitStatuses
{
public StatusValue Stress { get; set; }
@@ -82,6 +94,9 @@ public static class UnitComponents
}
}
+ ///
+ /// 单位标签组件
+ ///
public sealed class UnitTags
{
public string DisciplineId { get; set; }
@@ -92,19 +107,28 @@ public static class UnitComponents
public bool HasTrait(string traitId) => TraitIds.Contains(traitId);
}
+ ///
+ /// 单位指派组件
+ ///
public sealed class UnitAssignment
{
public Guid? CurrentTaskId { get; set; }
}
+ ///
+ /// 单位位置组件
+ ///
public sealed class UnitPlacement
{
public GridPosition Current { get; set; } = GridPosition.Zero;
public GridPosition Target { get; set; } = GridPosition.Zero;
}
+ ///
+ /// 单位装备组件
+ ///
public sealed class UnitEquipment
{
public List EquippedItemIds { get; } = new();
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Models/UnitModel.cs b/scripts/Models/UnitModel.cs
index 4ababc1..ccd1e8a 100644
--- a/scripts/Models/UnitModel.cs
+++ b/scripts/Models/UnitModel.cs
@@ -17,20 +17,49 @@ namespace Models;
///
public sealed class UnitModel
{
+ ///
+ /// 身份组件
+ ///
public UnitComponents.UnitIdentity Identity { get; }
+ ///
+ /// 属性组件
+ ///
public UnitComponents.UnitAttributes Attributes { get; }
+ ///
+ /// 状态组件
+ ///
public UnitComponents.UnitStatuses Statuses { get; }
+ ///
+ /// 标签组件
+ ///
public UnitComponents.UnitTags Tags { get; }
+ ///
+ /// 指派组件
+ ///
public UnitComponents.UnitAssignment Assignment { get; }
+ ///
+ /// 位置组件
+ ///
public UnitComponents.UnitPlacement Placement { get; }
+ ///
+ /// 装备组件
+ ///
public UnitComponents.UnitEquipment Equipment { get; }
+ ///
+ /// 名字(便捷访问)
+ ///
public string Name
{
get => Identity.Name;
set => Identity.Name = value;
}
+ ///
+ /// 构造函数
+ ///
+ /// 名字
+ /// 随机数生成器
public UnitModel(string name, Random random = null)
{
Identity = new UnitComponents.UnitIdentity(name);
@@ -41,4 +70,4 @@ public sealed class UnitModel
Placement = new UnitComponents.UnitPlacement();
Equipment = new UnitComponents.UnitEquipment();
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Player.cs b/scripts/Player.cs
index ebcea44..dc2755f 100644
--- a/scripts/Player.cs
+++ b/scripts/Player.cs
@@ -2,6 +2,9 @@ using Godot;
using System;
using System.Collections.Generic;
+///
+/// 玩家数据管理类
+///
public partial class Player : Node
{
///
@@ -37,12 +40,23 @@ public partial class Player : Node
public int Total => Facility + Operational + Labor;
}
+ ///
+ /// 时间轴类型
+ ///
public class TimelineType
{
+ ///
+ /// 内部日期
+ ///
public DateOnly InternalDate { get; set; }
private Dictionary> _events;
+ ///
+ /// 订阅事件
+ ///
+ /// 日期
+ /// 事件UUID
public void Subscribe(DateOnly date, Guid eventUuid)
{
_events ??= new Dictionary>();
@@ -50,6 +64,11 @@ public partial class Player : Node
_events[date].Add(eventUuid);
}
+ ///
+ /// 取消订阅事件
+ ///
+ /// 日期
+ /// 事件UUID
public void Unsubscribe(DateOnly date, Guid eventUuid)
{
if (_events == null) return;
@@ -57,6 +76,9 @@ public partial class Player : Node
_events[date].Remove(eventUuid);
}
+ ///
+ /// 进入下一天
+ ///
private void NextDay()
{
if (_events == null) return;
@@ -78,27 +100,53 @@ public partial class Player : Node
}
}
+ ///
+ /// 附加计时器
+ ///
+ /// 计时器
public void Attach(Timer ticker)
{
ticker.Timeout += NextDay;
}
+ ///
+ /// 构造函数
+ ///
+ /// 开始日期
public TimelineType(DateOnly startDate)
{
InternalDate = startDate;
}
+ ///
+ /// 事件触发委托
+ ///
public delegate void EventTriggeredEventHandler(DateOnly date, Guid eventUuid);
+ ///
+ /// 事件触发事件
+ ///
public event EventTriggeredEventHandler OnEventTriggered;
+ ///
+ /// 日期变更委托
+ ///
public delegate void DayChangedEventHandler(DateOnly date);
+ ///
+ /// 日期变更事件
+ ///
public event DayChangedEventHandler OnDayChanged;
}
+ ///
+ /// 预算实例
+ ///
public static BudgetType Budget { get; set; } = new();
+ ///
+ /// 时间轴实例
+ ///
public static readonly TimelineType Timeline = new(DateOnly.Parse("2024/11/17"));
///
@@ -117,13 +165,20 @@ public partial class Player : Node
public static DateOnly Date { get; set; }
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Res.cs b/scripts/Res.cs
index 96c90d9..4651b3e 100644
--- a/scripts/Res.cs
+++ b/scripts/Res.cs
@@ -1,18 +1,31 @@
using Godot;
using System;
+///
+/// 资源管理类
+///
public partial class Res : Node
{
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
}
+ ///
+ /// 资源类型枚举
+ ///
public enum Type
{
Accessory,
@@ -23,16 +36,32 @@ public partial class Res : Node
Phone
}
+ ///
+ /// 获取随机资源路径
+ ///
+ /// 资源类型
+ /// 资源路径
public static string GetRandom(Type resType)
{
return GetRandom(resType, false);
}
+ ///
+ /// 转换为16x16精灵路径
+ ///
+ /// 原路径
+ /// 16x16路径
private static string To16Path(string path)
{
return path.Replace("_48x48_", "_").Replace("_48x48", "");
}
+ ///
+ /// 获取随机资源路径(可选16x16)
+ ///
+ /// 资源类型
+ /// 是否使用16x16精灵
+ /// 资源路径
public static string GetRandom(Type resType, bool use16X16Sprites)
{
var resources = allResources[(int)resType];
@@ -48,6 +77,9 @@ public partial class Res : Node
return ResourceLoader.Exists(path16) ? path16 : path;
}
+ ///
+ /// 身体资源列表
+ ///
public static readonly string[] Body =
[
"res://resources/characters/bodies/Body_48x48_01.png",
@@ -60,6 +92,9 @@ public partial class Res : Node
"res://resources/characters/bodies/Body_48x48_08.png"
];
+ ///
+ /// 饰品资源列表
+ ///
public static readonly string[] Accessory =
[
"res://resources/characters/accessories/Accessory_01_Ladybug_48x48_01.png",
@@ -145,6 +180,9 @@ public partial class Res : Node
"res://resources/characters/accessories/Accessory_19_Party_Cone_48x48_04.png"
];
+ ///
+ /// 眼睛资源列表
+ ///
public static readonly string[] Eye =
[
"res://resources/characters/eyes/Eyes_48x48_01.png",
@@ -156,6 +194,9 @@ public partial class Res : Node
"res://resources/characters/eyes/Eyes_48x48_07.png"
];
+ ///
+ /// 发型资源列表
+ ///
public static readonly string[] Hair =
[
"res://resources/characters/hairstyles/Hairstyle_01_48x48_01.png",
@@ -360,6 +401,9 @@ public partial class Res : Node
"res://resources/characters/hairstyles/Hairstyle_29_48x48_06.png"
];
+ ///
+ /// 服装资源列表
+ ///
public static readonly string[] Outfit =
[
"res://resources/characters/outfits/Outfit_01_48x48_01.png",
@@ -496,6 +540,9 @@ public partial class Res : Node
"res://resources/characters/outfits/Outfit_33_48x48_03.png"
];
+ ///
+ /// 手机资源列表
+ ///
public static readonly string[] Smartphone =
[
"res://resources/characters/smartphones/Smartphone_48x48_1.png",
@@ -515,4 +562,4 @@ public partial class Res : Node
Smartphone
];
-}
+}
\ No newline at end of file
diff --git a/scripts/SceneTransit.cs b/scripts/SceneTransit.cs
index a606f6b..f6f2581 100644
--- a/scripts/SceneTransit.cs
+++ b/scripts/SceneTransit.cs
@@ -1,9 +1,15 @@
using Godot;
using System;
+///
+/// 场景过渡控制器
+///
public partial class SceneTransit : CanvasLayer
{
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
Layer = -1;
@@ -11,10 +17,21 @@ public partial class SceneTransit : CanvasLayer
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
}
+ ///
+ /// 切换场景
+ ///
+ /// 下一场景路径
+ /// 是否需要加载资源
+ /// 过渡动画名称
+ /// 等待时间
public async void Transit(string nextScene, bool needLoadResources = true, string animation = "transit", float waitSecond = 0)
{
SetProcess(true);
@@ -39,4 +56,4 @@ public partial class SceneTransit : CanvasLayer
SetProcess(false);
}
-}
+}
\ No newline at end of file
diff --git a/scripts/Student.cs b/scripts/Student.cs
index 277769a..ed803d6 100644
--- a/scripts/Student.cs
+++ b/scripts/Student.cs
@@ -5,15 +5,34 @@ using System.Linq;
using Models;
// ReSharper disable CheckNamespace
+///
+/// 学生角色控制器
+///
public partial class Student : CharacterBody2D
{
+ ///
+ /// 移动速度
+ ///
public float Speed { get; set; } = 8.0f;
+ ///
+ /// 跳跃速度
+ ///
public const float JumpVelocity = -400.0f;
+ ///
+ /// 是否使用16x16精灵
+ ///
[Export] public bool Use16X16Sprites { get; set; }
// --- MVP: Model Binding ---
+ ///
+ /// 学生数据模型
+ ///
public StudentModel Model { get; private set; }
+ ///
+ /// 绑定数据模型
+ ///
+ /// 学生模型
public void BindData(StudentModel model)
{
Model = model;
@@ -21,15 +40,35 @@ public partial class Student : CharacterBody2D
}
// --------------------------
+ ///
+ /// 下一个状态类型(未使用)
+ ///
public int NextType = -1;
private Queue _pathToGo = new();
private AnimationPlayer _animationPlayer;
+
+ ///
+ /// 角色状态枚举
+ ///
public enum CharacterState { Idle, Walking, Sitting, SittingDown, StandingUp }
+ ///
+ /// 当前状态
+ ///
public CharacterState State { get; set; } = CharacterState.Idle;
+
+ ///
+ /// 方向枚举
+ ///
public enum Direction { Up, Down, Left, Right }
+ ///
+ /// 目标方向
+ ///
public Direction TargetDirection { get; set; } = Direction.Up;
+ ///
+ /// 状态队列
+ ///
public Queue StateQueue { get; set; } = new();
private Vector2I _targetSpecialPosition;
@@ -54,6 +93,11 @@ public partial class Student : CharacterBody2D
State = StateQueue.Dequeue();
GlobalPosition = _lastWalkablePosition;
}
+
+ ///
+ /// 物理处理
+ ///
+ /// 时间间隔
public override void _PhysicsProcess(double delta)
{
if (StateQueue.Count > 0) {
@@ -141,6 +185,9 @@ public partial class Student : CharacterBody2D
// MoveAndSlide();
}
+ ///
+ /// 准备就绪时调用
+ ///
public override void _Ready()
{
base._Ready();
@@ -163,6 +210,10 @@ public partial class Student : CharacterBody2D
}
}
+ ///
+ /// 移动跟随路径
+ ///
+ /// 路径点列表
public void MoveFollowPath(List path)
{
foreach (var p in path)
@@ -171,8 +222,14 @@ public partial class Student : CharacterBody2D
}
}
+ ///
+ /// 关联的格子ID
+ ///
public Guid CubeId;
+ ///
+ /// 随机前往某处
+ ///
public void GoTo() {
if (State == CharacterState.SittingDown || State == CharacterState.StandingUp || State == CharacterState.Walking)
{
@@ -201,6 +258,9 @@ public partial class Student : CharacterBody2D
RandomChangeBody();
}
+ ///
+ /// 前往座位
+ ///
public void GoToSeat() {
if (State == CharacterState.SittingDown || State == CharacterState.StandingUp || State == CharacterState.Walking)
{
@@ -248,6 +308,9 @@ public partial class Student : CharacterBody2D
RandomChangeBody();
}
+ ///
+ /// 随机更换外观
+ ///
private void RandomChangeBody()
{
GetNode("parts/body").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.Body, Use16X16Sprites));
@@ -257,4 +320,4 @@ public partial class Student : CharacterBody2D
GetNode("parts/accessory").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.Accessory, Use16X16Sprites));
GetNode("parts/smartphone").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.Phone, Use16X16Sprites));
}
-}
+}
\ No newline at end of file
diff --git a/scripts/StudentName.cs b/scripts/StudentName.cs
index d75d196..7dffcca 100644
--- a/scripts/StudentName.cs
+++ b/scripts/StudentName.cs
@@ -2,20 +2,33 @@ using Godot;
using System;
using System.IO;
+///
+/// 学生姓名生成器
+///
public partial class StudentName : Node
{
// Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
+ ///
+ /// 每帧更新
+ ///
+ /// 帧间隔
public override void _Process(double delta)
{
}
- public string GenerateName()
- {
- string[] 姓氏 = { "大", "小", "飞", "傻", "呆", "雷", "东", "西", "王", "赵", "李", "张", "刘", "周" ,"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季", "麻", "强", "贾", "路", "娄", "危", "江", "童", "颜", "郭", "梅", "盛", "林", "刁", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田", "樊", "胡", "凌", "霍", "虞", "万", "支", "柯", "昝", "管", "卢", "莫", "经", "房", "裘", "缪", "干", "解", "应", "宗", "丁", "宣", "贲", "邓", "郁", "单", "杭", "洪", "包", "诸", "左", "石", "崔", "吉", "钮", "龚", "程", "嵇", "邢", "滑", "裴", "陆", "荣", "翁", "荀", "羊", "於", "惠", "甄", "麴", "家", "封", "芮", "羿", "储", "靳", "汲", "邴", "糜", "松", "井", "段", "富", "巫", "乌", "焦", "巴", "弓", "牧", "隗", "山", "谷", "车", "侯", "宓", "蓬", "全", "郗", "班", "仰", "秋", "仲", "伊", "宫", "宁", "仇", "栾", "暴", "甘", "钭", "厉", "戎", "祖", "武", "符", "刘", "景", "詹", "束", "龙", "叶", "幸", "司", "韶", "郜", "黎", "蓟", "薄", "印", "宿", "白", "怀", "蒲", "邰", "从", "鄂", "索", "咸", "籍", "赖", "卓", "蔺", "屠", "蒙", "池", "乔", "阴", "欎", "胥", "能", "苍", "双", "闻", "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵", "冉", "宰", "郦", "雍", "舄", "璩", "桑", "桂", "濮", "牛", "寿", "通", "边", "扈", "燕", "冀", "郏", "浦", "尚", "农", "温", "别", "庄", "晏", "柴", "瞿", "阎", "充", "慕", "连", "茹", "习", "宦", "艾", "鱼", "容", "向", "古", "易", "慎", "戈", "廖", "庾", "终", "暨", "居", "衡", "步", "都", "耿", "满", "弘", "匡", "国", "文", "寇", "广", "禄", "阙", "东", "殴", "殳", "沃", "利", "蔚", "越", "夔", "隆", "师", "巩", "厍", "聂", "晁", "勾", "敖", "融", "冷", "訾", "辛", "阚", "那", "简", "饶", "空", "曾", "毋", "沙", "乜", "养", "鞠", "须", "丰", "巢", "关", "蒯", "相", "查", "後", "荆", "红", "游", "竺", "权", "逯", "盖", "益", "桓", "公", "万俟", "司马", "上官", "欧阳", "夏侯", "诸葛", "闻人", "东方", "赫连", "皇甫", "尉迟", "公羊", "澹台", "公冶", "宗政", "濮阳", "淳于", "单于", "太叔", "申屠", "公孙", "仲孙", "轩辕", "令狐", "钟离", "宇文", "长孙", "慕容", "鲜于", "闾丘", "司徒", "司空", "亓官", "司寇", "仉", "督", "子车", "颛孙", "端木", "巫马", "公西", "漆雕", "乐正", "壤驷", "公良", "拓跋", "夹谷", "宰父", "谷梁", "晋", "楚", "闫", "法", "汝", "鄢", "涂", "钦", "段干", "百里", "东郭", "南门", "呼延", "归", "海", "羊舌", "微生", "岳", "帅", "缑", "亢", "况", "后", "有", "琴", "梁丘", "左丘", "东门", "西门", "商", "牟", "佘", "佴", "伯", "赏", "南宫", "墨", "哈", "谯", "笪", "年", "爱", "阳", "佟", "第五", "言", "福", "百", "家", "姓", "终"};
+ ///
+ /// 生成随机姓名
+ ///
+ /// 随机姓名
+ public string GenerateName()
+ { string[] 姓氏 = { "大", "小", "飞", "傻", "呆", "雷", "东", "西", "王", "赵", "李", "张", "刘", "周" ,"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季", "麻", "强", "贾", "路", "娄", "危", "江", "童", "颜", "郭", "梅", "盛", "林", "刁", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田", "樊", "胡", "凌", "霍", "虞", "万", "支", "柯", "昝", "管", "卢", "莫", "经", "房", "裘", "缪", "干", "解", "应", "宗", "丁", "宣", "贲", "邓", "郁", "单", "杭", "洪", "包", "诸", "左", "石", "崔", "吉", "钮", "龚", "程", "嵇", "邢", "滑", "裴", "陆", "荣", "翁", "荀", "羊", "於", "惠", "甄", "麴", "家", "封", "芮", "羿", "储", "靳", "汲", "邴", "糜", "松", "井", "段", "富", "巫", "乌", "焦", "巴", "弓", "牧", "隗", "山", "谷", "车", "侯", "宓", "蓬", "全", "郗", "班", "仰", "秋", "仲", "伊", "宫", "宁", "仇", "栾", "暴", "甘", "钭", "厉", "戎", "祖", "武", "符", "刘", "景", "詹", "束", "龙", "叶", "幸", "司", "韶", "郜", "黎", "蓟", "薄", "印", "宿", "白", "怀", "蒲", "邰", "从", "鄂", "索", "咸", "籍", "赖", "卓", "蔺", "屠", "蒙", "池", "乔", "阴", "欎", "胥", "能", "苍", "双", "闻", "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵", "冉", "宰", "郦", "雍", "舄", "璩", "桑", "桂", "濮", "牛", "寿", "通", "边", "扈", "燕", "冀", "郏", "浦", "尚", "农", "温", "别", "庄", "晏", "柴", "瞿", "阎", "充", "慕", "连", "茹", "习", "宦", "艾", "鱼", "容", "向", "古", "易", "慎", "戈", "廖", "庾", "终", "暨", "居", "衡", "步", "都", "耿", "满", "弘", "匡", "国", "文", "寇", "广", "禄", "阙", "东", "殴", "殳", "沃", "利", "蔚", "越", "夔", "隆", "师", "巩", "厍", "聂", "晁", "勾", "敖", "融", "冷", "訾", "辛", "阚", "那", "简", "饶", "空", "曾", "毋", "沙", "乜", "养", "鞠", "须", "丰", "巢", "关", "蒯", "相", "查", "後", "荆", "红", "游", "竺", "权", "逯", "盖", "益", "桓", "公", "万俟", "司马", "上官", "欧阳", "夏侯", "诸葛", "闻人", "东方", "赫连", "皇甫", "尉迟", "公羊", "澹台", "公冶", "宗政", "濮阳", "淳于", "单于", "太叔", "申屠", "公孙", "仲孙", "轩辕", "令狐", "钟离", "宇文", "长孙", "慕容", "鲜于", "闾丘", "司徒", "司空", "亓官", "司寇", "仉", "督", "子车", "颛孙", "端木", "巫马", "公西", "漆雕", "乐正", "壤驷", "公良", "拓跋", "夹谷", "宰父", "谷梁", "晋", "楚", "闫", "法", "汝", "鄢", "涂", "钦", "段干", "百里", "东郭", "南门", "呼延", "归", "海", "羊舌", "微生", "岳", "帅", "缑", "亢", "况", "后", "有", "琴", "梁丘", "左丘", "东门", "西门", "商", "牟", "佘", "佴", "伯", "赏", "南宫", "墨", "哈", "谯", "笪", "年", "爱", "阳", "佟", "第五", "言", "福", "百", "家", "姓", "终"};
string[] 名字前缀 = { "金", "猪", "兔", "猫", "鱼", "蛋", "胖", "大", "傻", "酷", "蠢", "聪", "萌", "暴","靖", "铭", "琛", "川", "承", "司", "斯", "宗", "骁", "聪", "在", "钩", "锦", "铎", "楚", "铮", "钦", "则", "楠", "景", "茗", "聿", "启", "尧", "言", "嘉", "桉", "桐", "筒", "竹", "林", "乔", "栋", "家", "翊", "松", "清", "澈", "泫", "浚", "润", "泽", "向", "凡", "文", "浦", "洲", "珩", "玄", "洋", "淮", "雨", "子", "云", "卓", "昱", "南", "晨", "知", "宁", "年", "易", "晗", "炎", "焕", "哲", "煦", "旭", "明", "阳", "朗", "典", "辰", "宸", "野", "安", "为", "亦", "岚", "也", "围", "以", "延", "允", "容", "恩", "衡", "宇", "硕", "已", "意", "也", "坤", "辰", "伊", "米", "安", "恩", "以", "容", "宛", "岚", "又", "衣", "亚", "悠", "允", "画", "灿", "夏", "珞", "煊", "晴", "彤", "诺", "宁", "恬", "钧", "灵", "昭", "琉", "晨", "曦", "南", "毓", "冉", "妍", "澜", "淇", "沐", "潆", "盈", "雨", "文", "冰", "雯", "溪", "子", "云", "汐", "潞", "淇", "妙", "涵", "楠", "景", "茗", "聿", "启", "尧", "言", "嘉", "桉", "桐", "筒", "竹", "林", "乔", "栋", "家", "翊", "松", "真", "心", "新", "悦", "西", "兮", "楚", "初", "千", "锐", "素", "锦", "静", "镜", "斯", "舒", "瑜", "童" };
string[] 名字后缀 = { "子", "郎", "妹", "宝", "儿", "汉", "君", "爷", "娃", "猪", "鬼", "鸟", "仔", "蛋","靖", "铭", "琛", "川", "承", "司", "斯", "宗", "骁", "聪", "在", "钩", "锦", "铎", "楚", "铮", "钦", "则", "楠", "景", "茗", "聿", "启", "尧", "言", "嘉", "桉", "桐", "筒", "竹", "林", "乔", "栋", "家", "翊", "松", "清", "澈", "泫", "浚", "润", "泽", "向", "凡", "文", "浦", "洲", "珩", "玄", "洋", "淮", "雨", "子", "云", "卓", "昱", "南", "晨", "知", "宁", "年", "易", "晗", "炎", "焕", "哲", "煦", "旭", "明", "阳", "朗", "典", "辰", "宸", "野", "安", "为", "亦", "岚", "也", "围", "以", "延", "允", "容", "恩", "衡", "宇", "硕", "已", "意", "也", "坤", "辰", "伊", "米", "安", "恩", "以", "容", "宛", "岚", "又", "衣", "亚", "悠", "允", "画", "灿", "夏", "珞", "煊", "晴", "彤", "诺", "宁", "恬", "钧", "灵", "昭", "琉", "晨", "曦", "南", "毓", "冉", "妍", "澜", "淇", "沐", "潆", "盈", "雨", "文", "冰", "雯", "溪", "子", "云", "汐", "潞", "淇", "妙", "涵", "楠", "景", "茗", "聿", "启", "尧", "言", "嘉", "桉", "桐", "筒", "竹", "林", "乔", "栋", "家", "翊", "松", "真", "心", "新", "悦", "西", "兮", "楚", "初", "千", "锐", "素", "锦", "静", "镜", "斯", "舒", "瑜", "童" };
diff --git a/scripts/TestMap.cs b/scripts/TestMap.cs
index ad71534..0be23e8 100644
--- a/scripts/TestMap.cs
+++ b/scripts/TestMap.cs
@@ -1,26 +1,32 @@
using Godot;
using System;
-
+///
+/// 测试地图层
+///
public partial class TestMap : TileMapLayer
{
///
- /// The last cell that was highlighted. Used to avoid unnecessary updates.
+ /// 上一次高亮的单元格。用于避免不必要的更新。
///
private Vector2I _lastHighlightCell;
private readonly Vector2I _highlightTileCoord = new(0, 5);
private readonly Vector2I _vector2INegOne = new(-1, -1);
- // Called when the node enters the scene tree for the first time.
+
+ // Called when the node enters the scene tree for the first time.
+ ///
+ /// 场景加载完成时调用
+ ///
public override void _Ready()
{
- // Initialize the lastHighlightCell to an invalid value.
+ // 初始化最后高亮单元格为无效值。
_lastHighlightCell = _vector2INegOne;
}
///
- /// Called every frame.
+ /// 每帧更新。
///
- /// the elapsed time since the previous frame.
+ /// 距离上一帧的时间间隔。
public override void _Process(double delta)
{
Vector2 mousePos = GetLocalMousePosition();
@@ -36,5 +42,4 @@ public partial class TestMap : TileMapLayer
SetCell(cell, 0, _highlightTileCoord);
}
}
-
-}
+}
\ No newline at end of file
diff --git a/scripts/TileMapping.cs b/scripts/TileMapping.cs
index 33555cb..b609565 100644
--- a/scripts/TileMapping.cs
+++ b/scripts/TileMapping.cs
@@ -3,23 +3,39 @@ using System;
using System.Collections.Generic;
using System.Linq;
+///
+/// 图块映射辅助类
+///
public partial class TileMapping : Node
{
///
- /// From tile coordinates to pixel coordinates. If null, use the offset instead.
+ /// 从图块坐标到像素坐标的映射。如果不为空,则使用此映射。
///
private Dictionary _pixelMap;
///
- /// If pixelMap is null, use this offset to convert tile coordinates to pixel coordinates.
+ /// 如果 pixelMap 为空,使用此偏移量将图块坐标转换为像素坐标。
///
private Vector2I _pixelOffset;
+
+ ///
+ /// 图块区域
+ ///
private Rect2I _tileRect;
+ ///
+ /// 构造函数,使用坐标映射字典
+ ///
+ /// 坐标映射字典
public TileMapping(Dictionary map) {
_pixelMap = map;
_pixelOffset = new Vector2I(-int.MaxValue, -int.MaxValue);
}
+ ///
+ /// 构造函数,使用偏移量和区域
+ ///
+ /// 偏移量
+ /// 区域
public TileMapping(Vector2I offset, Rect2I rect) {
_pixelMap = null;
_pixelOffset = offset;
@@ -28,6 +44,10 @@ public partial class TileMapping : Node
public TileMapping() {}
+ ///
+ /// 应用映射到TileMapLayer
+ ///
+ /// TileMapLayer
public void Apply(TileMapLayer layer) {
// if pixelMap is not null, use all the pairs in pixelMap to set the tiles.
if (_pixelMap != null) {
@@ -46,4 +66,4 @@ public partial class TileMapping : Node
}
}
}
-}
+}
\ No newline at end of file