【免费下载链接】Jedi-Academy
Star Wars Jedi Knight: Jedi Academy
Jedi-Academy(《星球大战:绝地武士2:绝地学院》)把整个游戏界面写成纯文本.menu文件:主菜单、暂停菜单、联机大厅全部由base/ui目录下的 90 余个脚本文件与code/ui中的 C++ 解析器共同驱动,没有可视化编辑器。本文带你快速看懂这套 Jedi-Academy UI 系统的加载流程与文件结构,并给出新手上手的改法。
🧩 UI 系统全景:目录与文件职责
整套界面由两部分组成,理解它们的分工是入门的关键:
| 目录 | 职责 | 关键文件 |
|---|---|---|
| base/ui/ | 界面"数据":菜单布局、按钮、字体、音效引用 | main.menu、menus.txt |
| base/ui/jamp/ | 多人模式(JAMP)菜单 | multiplayer.menu、rules_games.menu |
| code/ui/ | 界面"引擎":加载、解析、绘制、事件响应 | ui_main.cpp、ui_shared.cpp |
💡 简单说:
.menu文件负责"长什么样、点了干什么",code/ui里的 C++ 代码负责"把文本变成可交互的窗口"。改界面通常只动文本,不必碰代码。
清单文件(.txt)则负责列出"这一套界面要加载哪些.menu"。游戏启动时加载的是 base/ui/menus.txt:
loadMenu { "ui/main.menu" } loadMenu { "ui/newgame.menu" } loadMenu { "ui/character.menu" } loadMenu { "ui/saber.menu" } ...🔄 菜单加载流程:从 menus.txt 到 .menu 的四步解析
整个加载链条非常线性,每一步都能在源码中找到对应函数:
- 选择清单—
UI_Load()读取 cvarui_menuFiles,默认为ui/menus.txt;若处于游戏内暂停状态,则改用ui/ingame.txt。见 ui_main.cpp#L3932-L3966 - 解析清单—
UI_LoadMenus()逐 token 扫描清单文件,遇到loadmenu关键词就取出后面的文件路径。见 ui_main.cpp#L3855-L3925 - 加载单个文件—
Load_Menu()读取该.menu文件并交给UI_ParseMenu(),后者识别两大块:assetGlobalDef(全局资源)和menuDef(菜单窗口) - 解析控件— 每个
itemDef由Item_Parse()处理,字段名通过关键词哈希表快速匹配到解析函数,未知字段会打印Unknown item keyword警告。见 ui_shared.cpp#L5316-L5372
menus.txt ──loadMenu──▶ main.menu ──assetGlobalDef──▶ 字体/光标/音效 └──menuDef─────▶ 窗口 + itemDef(按钮/滑块/列表)📄 解剖一个 .menu 文件:三大代码块
以 base/ui/main.menu(主菜单,548 行)为例,文件由三部分组成:
| 代码块 | 作用 | main.menu 中的示例 |
|---|---|---|
assetGlobalDef | 本菜单的全局资源:字体、光标、焦点音效、渐隐参数 | smallFont "aurabesh" 18、focuscolor 0 0 1 1 |
menuDef | 一个完整窗口:名字、坐标、焦点设置、ESC 行为 | name "mainMenu"、rect 0 0 640 480 |
itemDef | 窗口内的单个控件:按钮、背景图、文本、模型 | name newgamebutton、type ITEM_TYPE_BUTTON |
assetGlobalDef还内置了一个precacheSound列表,把角色定制界面的选头、选躯干、选光剑等音效提前载入内存,保证点击时零延迟。
一个完整的按钮长什么样
主菜单的"新建游戏"按钮(main.menu第 211-246 行)展示了 Jedi Academy 按钮的全部套路:
itemDef { name newgamebutton type ITEM_TYPE_BUTTON rect 36 212 130 24 text @MENUS_NEW action { play "sound/interface/button1.wav" ; close all ; open newgamefirstMenu } }注意三个细节:
rect是x y w h,坐标系以 640×480 为基准@MENUS_NEW不是死文本,而是字符串引用,运行时通过SE_GetString()从本地化文件中取真正文案(ui_shared.cpp#L5397-L5401),这是实现多语言的基础action里close all+open newgamefirstMenu就是菜单间跳转的全部机制——靠名字互相引用,形成一张菜单导航图
悬停高亮:mouseEnter / mouseExit
每个按钮都配了一个"发光底板"button_glow(默认隐藏),鼠标进入时显示并定位到按钮下方:
mouseEnter { show button_glow setitemrect button_glow 16 210 210 32 }这套"隐藏装饰 + 事件切换可见性"的模式贯穿整个菜单系统,是纯文本描述状态变化的典型范例。
🎮 控件类型与本地化:menudef.h 里的"零件库"
itemDef的type字段对应 code/ui/menudef.h 中定义的控件枚举,Jedi Academy 一共提供 15 种:
| 控件类型 | 用途 | 典型场景 |
|---|---|---|
ITEM_TYPE_TEXT | 静态文本 | 菜单标题 |
ITEM_TYPE_BUTTON | 按钮 | "新建游戏" |
ITEM_TYPE_EDITFIELD | 文本输入,绑定 cvar | 玩家名字 |
ITEM_TYPE_SLIDER | 滑杆 | 音量、鼠标灵敏度 |
ITEM_TYPE_LISTBOX | 滚动列表 | 存档选择、地图选择 |
ITEM_TYPE_MODEL | 3D 模型展示 | 角色定制界面预览 |
ITEM_TYPE_COMBO/ITEM_TYPE_MULTI | 下拉/枚举列表 | 难度、游戏类型 |
ITEM_TYPE_BIND | 按键绑定 | 控制设置 |
ITEM_TYPE_TEXTSCROLL | 滚动长文本 | 过场说明 |
其中ITEM_TYPE_LISTBOX最值得新手了解:列表数据不是写死在.menu里的,而是由menudef.h中的FEEDER_*常量指定数据源(如FEEDER_SAVEGAMES读存档、FEEDER_MAPS读地图、FEEDER_SERVERS读服务器列表),C++ 引擎负责填充。文本、列表、按钮各司其职。
🗂 游戏内菜单与多人模式:谁在用哪套清单
Jedi Academy 的菜单按"场景"分成几套独立清单,互不干扰:
| 清单文件 | 使用场景 |
|---|---|
| base/ui/menus.txt | 启动后的主界面(主菜单、角色定制、设置) |
| base/ui/ingame.txt | 游戏中按 ESC 的暂停菜单、数据板(datapad) |
| base/ui/tier1.txt | 章节过场时的地图选择 |
| base/ui/jamp/ | 多人模式全部 51 个菜单:大厅、投票、围城模式 |
多人菜单由 codemp/ui/ 下的 UI 模块加载。ingame.txt里能看到"数据板"系列菜单(datapadforcepowers.menu、datapadweapons.menu等),对应游戏中按 R 键查看的光剑面板——它同样是纯.menu文件,只是绘制风格换成了全息数据板样式。
⌨️ 一个实用技巧:
ui_menuFiles这个 cvar 可以在控制台直接改写,指向你自己的清单文件,就能在不替换原菜单的情况下测试一套新界面——这正是当年 mod 作者的做法。
🔧 动手上手:改你的第一个菜单
仓库是只读的,先把base/ui/main.menu复制到本地游戏目录再动手。推荐的新手三步骤:
- 改文案:把
main.menu中newgamebutton的descText从@MENUS_START_A_NEW_GAME换成纯文本(去掉@前缀),观察悬停描述变化 - 改布局:把
exitgamebutton的rect 255 444 130 24中的 x 坐标改成40,退出按钮就跑到左边了 - 加菜单:新建
mymenu.menu(照抄main.menu改按钮文字),再在menus.txt末尾加一行loadMenu { "ui/mymenu.menu" },并从主菜单某个按钮的action里open它
遇到解析问题不要慌:控制台会提示Unknown item keyword 'xxx'(字段名拼错)或Invalid keyword 'xxx'(块层级写错),按提示回查 ui_main.cpp#L3796 附近的解析逻辑即可。
🖼 进阶工具:用 ModView 浏览界面素材
.menu里background字段引用的gfx/menus/*贴图、字体文件等资源,可以配合仓库自带的 ModView 工具查看。该工具位于 tools/ModView/,是一个独立的资源浏览器:
把.menu与它引用的贴图、音效对照着看,"文本 → 窗口"的完整映射关系就清晰了。
📚 总结:.menu 文件速查表
| 想做什么 | 去哪改 |
|---|---|
| 换按钮文字/颜色 | 对应.menu的itemDef(text、forecolor) |
| 换菜单背景 | itemDef的background字段 +gfx/menus/贴图 |
| 改按钮跳转目标 | action块中的open xxxMenu |
| 改字体/全局音效 | assetGlobalDef块 |
| 增删菜单文件 | 对应清单文件(menus.txt/ingame.txt) |
| 新增控件行为 | 需改 code/ui/ui_shared.cpp 的关键词解析表 |
核心结论:Jedi-Academy 的 UI 系统是一套"文本即界面"的声明式设计——.txt清单管加载、.menu文件管布局与交互、C++ 解析器管执行。90 余个菜单文件全部可读可改,这使它成为研究 Quake3/JK2 家族 UI 架构的最佳范例,也是自制 mod 界面最直接的切入点。
【免费下载链接】Jedi-Academy
Star Wars Jedi Knight: Jedi Academy
相关推荐
Jedi-Academy数据文件格式速览:.npc、.veh、.menu如何定义游戏内容
Jedi Academy数据文件格式速览:.npc、.veh、.menu如何定义游戏内容 《星球大战:克隆人……不,是《星球大战 绝地骑士:绝地学院》(Star
Jedi-Academy实体系统揭秘:gentity_t与Spawn变量如何构建游戏世界
Jedi Academy实体系统揭秘:gentity_t与Spawn变量如何构建游戏世界 Jedi Academy 是经典射击游戏《星球大战 绝地武士:绝地学院
Jedi-Academy过场系统Icarus终极指南:脚本语言如何驱动电影级剧情
Jedi Academy过场系统Icarus终极指南:脚本语言如何驱动电影级剧情 Jedi Academy(星球大战:原力释放 绝地学院)开源仓库中的 Icar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考