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