附录 B:导读:官方示例的阅读方法

附录 B:导读:官方示例的阅读方法

0 按照特定顺序阅读官方示例

SDK 包含官方示例。如果一上来就阅读大型示例,UI、AI、车辆和状态管理会同时出现,这可能会让人感到困惑。

首先,按以下顺序阅读它们。

  1. docs/pages
  2. code/types/mod/index.d.ts
  3. GodotProject/mods/_StartHere_BasicTemplate
  4. 按目的分类的示例

按这个顺序,你可以从官方文档中掌握概念,检查类型定义中的 API 名称,在最小模板中查看事件的形状,然后进入实战示例。

1 SDK 文件夹的阅读方法

位置 看什么 阅读方式
docs/pages/getting_started.html 启动 Godot、Portal Setup 和打开关卡的步骤 确认环境构建
docs/pages/spatial_editor.html Spatial Editor 操作、Object Library、导出 第 4 章的补充
docs/pages/gameplay_logic.html TypeScript、日志、UI、AI、Spawn、ObjId 参考 第 6 章的补充
docs/pages/tips_tricks.html 性能说明 第 8 章和第 9 章的补充
code/types/mod/index.d.ts mod 命名空间中的所有 API 搜索函数名确认用法
GodotProject/mods 官方示例 按目的阅读

如果你遇到不知道的 API,请先在 index.d.ts 中搜索函数名。Portal 的 TypeScript 最终会调用 mod 命名空间中的函数,所以这里就是字典。

2 最先阅读的官方示例

示例 首先阅读的理由
_StartHere_BasicTemplate 汇集了事件函数、GetObjIdMessageCreateVector 等基本写法
PortalGadgetExample 查看 Portal Gadget 输入事件、RayCast 和单个玩家反应
FixedCameraExample 可以查看相机切换和 UI 按钮事件的基础知识
VL7Example 可以查看特殊对象的进入 / 退出事件
BumperCars 阅读小游戏循环、车辆和状态管理的示例
GibraltarGrandprix 阅读比赛、检查点、名次 UI 和车辆选择的示例

对于初学者来说,_StartHere_BasicTemplate 就足够了。复杂示例作为可运行的成品很有吸引力,但信息量太大,不适合作为最开始的教材。

3 读取示例时的备忘表

查看项目 注意事项
入口事件 OnGameModeStartedOnPlayerDeployedOnPlayerInteract
状态管理 phaseGameStatePlayerProfile
ObjId 参照 获取位置,如 GetInteractPoint(500)
UI 在哪里创建、更新和删除
等待处理 mod.Wait 的周期和目的
多重触发对策 isProcessing...,冷却时间,标志

只需填写此表即可查看示例的整体图。先读结构,而不是一上来读完整代码。这听起来可能很夸张,但确实有用。

4 想从官方示例中吸收的写法

如果你阅读一些官方示例,即使细节有所不同,你也会看到相似的方式。
这不仅仅是一种偏好,它是一种使更大的代码更容易阅读、更容易修复以及更容易以后扩展的方法。

请注意,移到 unsupported 下的示例中也有一些看起来很方便的写法。
但是,本文档只采用目前位于 GodotProject/mods 的受支持示例中可以读到的做法。

1. 把设置值集中到开头

将参与者数量、时间限制、调试标志、候选车辆、检查点定义、UI 名称等放在文件顶部。

如果你直接在处理中间写入 10500true 等值,之后调整时就会变成搜索噩梦。
如果一开始就把它们集中起来,调整这个模式时就知道该看哪里。

const MIN_PLAYERS = 2;
const COUNTDOWN_SECONDS = 10;
const DEBUG = false;
const VEHICLE_POOL = [mod.VehicleList.Quadbike, mod.VehicleList.GolfCart];

第 7 章中的 ids.tsconfig.ts 也是这个想法的延伸。
只要将数字和设置更改为名称,代码就变得更容易阅读。

2. 当代码变大后,用类划分职责

在较大的示例中,例如 BumperCarsGibraltarGrandprixAcePursuit,状态管理、玩家管理和 UI 管理被分为不同的类。

这并不意味着你应该将所有 Portal 代码变成一个类。
一开始只用函数就足够了。然而,随着每个玩家的状态和 UI 数量的增加,如果你根据职责将它们分成不同的类,将会更容易阅读。

角色 示例
游戏整体 GameState,开始条件,胜者判定,结束处理
每个玩家 PlayerProfile,Ready 状态、车辆、分数、个人 UI
整个比赛 TrackData,检查点,圈数,获胜者
UI 创建、更新、关闭、删除

使用类时重要的不是增加“有名字的箱子”,而是把会因为同一个理由一起变化的处理放在同一个地方。
例如,如果改变玩家的 Ready 状态、更新 Ready 显示以及离开时关闭 UI 的处理分散在各处,之后肯定很难追踪。

3. UI 要分开创建、更新和关闭

UI 是特别容易发挥类化效果的地方。
在大型示例中,创建 widget、更新显示内容、隐藏 / 删除的处理是分开的。

当你想要更改显示内容、修复忘记关闭屏幕或更改每个玩家的显示时,这可以让你更轻松地知道该改哪里。

class ReadyUpUI {
  constructor(private player: mod.Player) {}

  update(): void {
    // Update text and visibility.
  }

  close(): void {
    // Hide or delete widgets.
  }
}

乍一看似乎有点夸张,但 UI 越多,效果就越好。
只要分离“创建”、“更新”和“关闭”,以后添加表现效果和状态就会更容易。

结论

只要按正确顺序阅读,官方示例就是很强的学习材料。

首先,把 docs/pagesindex.d.ts 当作字典,并用 _StartHere_BasicTemplate 掌握事件的形状。然后阅读 GodotProject/mods 下按目的划分的示例。
接着,不要照搬示例的全部内容,而是把设置值集中管理、用类分离职责、UI 管理方式这些写法吸收到自己的代码中。本书的附录 B 也只介绍这个文件夹中的示例。


📘 **在下一章“附录 B:示例程序说明'_StartHere_BasicTemplate'”**中,我们将解释你应该首先阅读的基本模板。