9.3 KiB
9.3 KiB
游戏设计器 UI 优化(布局撑满 + 元素复选框 + 双语标签)— 设计
- 日期:2026-07-22
- 状态:设计已确认,待实现
- 范围:编辑器工具层
addons/game_designer/,游戏运行时代码与数据文件格式零改动
1. 背景与问题
用户反馈游戏设计器三点待优化:
- 输入框无法完整显示内容 ——
designer_ui.gd的line()/opt()/spin()只设固定最小宽度、无SIZE_EXPAND_FILL,控件不随面板拉伸,长文本(显示名/描述/VFX/JSON/长中文选项)被截断。 - 法术元素标签用逗号文本易错 —— 应改可视化控件。元素标签是多值(如
plasma_storm=["tag:water","tag:lightning"])。 - 部分显示仍为纯英文 ——
spell_tab.TYPE_NAMES/LOGIC_OPS、wave_tab.TYPE_NAMES、resonance_tab.MATCH等为纯英文。要求统一**双语(中文 English)**显示,含 spell_tab(其DMG_LABELS/ST_LABELS现为纯中文,也改双语)。
词表事实
- 元素标签词表(全数据仅这 5 个):
tag:fire 火/tag:ice 冰/tag:lightning 雷/tag:water 水/tag:poison 毒。 - 枚举整数来源:
DamageType(0物理/1火/2冰/3雷/4毒/5奥术)、StatusID(0无/1燃烧/2冻结/3中毒/4潮湿/5沾油/6眩晕/7连击/8易伤)。
2. 布局修复(全 7 页,中央改动)
addons/game_designer/designer_ui.gd:line() / opt() / spin() 三个工厂各追加:
ctrl.size_flags_horizontal = Control.SIZE_EXPAND_FILL
效果:行内 cell_label(70px,autosize,不变)之后,输入控件吃掉剩余宽度;表格页(敌人/波次)各列随之填满面板宽度。零数据改动,全 7 页受益。
3. 共享元素词表(designer_ui.gd 新增常量)
const ELEM_LABELS := ["火 Fire", "冰 Ice", "雷 Lightning", "水 Water", "毒 Poison"] # 显示(双语)
const ELEM_TAGS := ["tag:fire", "tag:ice", "tag:lightning", "tag:water", "tag:poison"] # 存储,index 对齐
spell_tab(复选框)与 resonance_tab(元素下拉)共用,单一事实源。通过 UI.ELEM_LABELS / UI.ELEM_TAGS 访问(const UI = preload(designer_ui.gd),常量可跨脚本访问)。
4. spell_tab —— 元素复选框 + 双语标签
4.1 元素标签复选框(替代 _tags 单行文本)
- UI:一行「元素标签」标签 + 5 个 CheckBox(文本取
UI.ELEM_LABELS);下方一行「自定义标签」+ 小 LineEdit(收纳非元素 tag,防丢)。 - 新增成员:
var _elem_checks: Array = [](5 个 CheckBox)、var _custom_tags: LineEdit。 - 加载(
_on_select):var etags: Array = d.get("element_tags", []) for i in _elem_checks.size(): _elem_checks[i].button_pressed = UI.ELEM_TAGS[i] in etags var custom := [] for t in etags: if not (t in UI.ELEM_TAGS): custom.append(String(t)) _custom_tags.text = ",".join(custom) - 应用(
_on_apply,替换原_tags解析块):var tags: Array = [] for i in _elem_checks.size(): if _elem_checks[i].button_pressed: tags.append(UI.ELEM_TAGS[i]) for t in _custom_tags.text.split(",", false): var s := t.strip_edges() if s != "" and not (s in tags): tags.append(s) - ⚠️ 多元素法术会被规整为固定元素顺序(火冰雷水毒),
element_tags语义为集合、顺序无意义——属预期简化(回读比较按集合)。
4.2 双语标签(仅显示;存储 index/key 不变)
const TYPE_NAMES := ["动作 ACTION", "修饰 MODIFIER", "触发 TRIGGER", "逻辑 LOGIC"]
const ACTION_KINDS := ["弹道 Projectile", "毒池 Zone", "召唤 Summon"]
const LOGIC_OPS := ["every_n_shots", "if_hp_below", "if_enemy_nearby", "loop"] # 存储 key,不变
const LOGIC_OP_LABELS := ["每 N 次 every_n_shots", "生命低于 if_hp_below", "附近有敌 if_enemy_nearby", "循环 loop"] # 新增,供下拉显示
const DMG_LABELS := ["物理 Physical", "火 Fire", "冰 Ice", "雷 Lightning", "毒 Poison", "奥术 Arcane"]
const ST_LABELS := ["无 None", "燃烧 Burn", "冻结 Freeze", "中毒 Poison", "潮湿 Wet", "沾油 Oily", "眩晕 Stun", "连击 Combo", "易伤 Vuln"]
_lop下拉改用UI.opt(LOGIC_OP_LABELS, 0);_read_meta仍meta["logic_op"] = LOGIC_OPS[_lop.selected],_on_select仍_lop.selected = LOGIC_OPS.find(...)(index↔key 逻辑不变,只换显示数组)。- 列表前缀
"[%s] %s" % [TYPE_NAMES[...], sid]变为"[动作 ACTION] action_spark_bolt"(可接受)。
5. wave_tab —— 双语标签
const TYPE_NAMES = ["杂兵 Basic", "快速 Fast", "护甲 Armored", "精英 Elite", "首领 MiniBoss", "终焉 Boss"]
const BOSS_NAMES = ["无 None", "首领 MiniBoss", "终焉 Boss"] # 存储走 BOSS_VALS,不变
(存储均为 index / BOSS_VALS,改标签零数据影响。)
6. resonance_tab —— 双语标签 + 元素下拉
- 匹配方式:
MATCH(存储 keyadjacent/anywhere_in_deck)不变;新增const MATCH_LABELS = ["相邻 adjacent", "卡组内任意 anywhere_in_deck"]供下拉显示。_match = _row("匹配方式", UI.opt(MATCH_LABELS, 0));_on_apply仍"match": MATCH[_match.selected];_on_select仍_match.selected = max(0, MATCH.find(...))。 - 元素 A / B:
_p0/_p1由 LineEdit →UI.opt(UI.ELEM_LABELS, 0)。- 加载:
_p0.selected = max(0, UI.ELEM_TAGS.find(String(p0)))(非元素值回退第 0 项)。 - 应用:
"pattern": [UI.ELEM_TAGS[_p0.selected], UI.ELEM_TAGS[_p1.selected]]。 - 列表显示
_refresh用 pattern 原值(tag 串),不变。 - ⚠️ 若某配方 pattern 含非元素值(现数据无),会被下拉回退丢失——现
resonance.json全为元素,风险为零;如未来需要非元素 pattern 再扩展。
- 加载:
7. 既有双语标签归一为「中文 English」序
统一所有枚举下拉显示为「中文 English」序(存储均为 index,改文案零数据影响):
core_tab.gd(addons/game_designer/core_tab.gd):(const TOPO = ["线性 LINEAR", "矩阵 MATRIX", "电路 CIRCUIT"] const FEAT = ["无 None", "记忆 PERSISTENT_MEMORY", "双流 DUAL_STREAM", "末位施法 ALWAYS_CAST_LAST", "洗牌 SHUFFLE_DECK", "无限法术 INFINITE_SPELLS"]FEAT原有 3 项纯英文ALWAYS_CAST_LAST/SHUFFLE_DECK/INFINITE_SPELLS补中文;topology/feature_tags存 index 不变。)status_tab.gd(addons/game_designer/status_tab.gd):(const STACK = ["刷新 REFRESH", "叠层 INTENSITY", "独立 INDEPENDENT"]stack_mode存 index 不变。)
不改:
enemy_tab.NAMES(["杂兵 Basic", ...])已是「中文 English」序,且 enemyname是持久化字段(写入 enemies.json)——保持原样。balance_tab标签本就中文(敌人血量×/初学者/MiniBoss(W8) 血量等),无纯英文枚举下拉,无需改。
全 7 页均受益于第 2 点布局撑满。
8. 组件边界与改动清单
| 文件 | 改动 |
|---|---|
designer_ui.gd |
line/opt/spin 加 SIZE_EXPAND_FILL;新增 ELEM_LABELS/ELEM_TAGS 常量 |
spell_tab.gd |
元素复选框 + 自定义框替换 _tags;TYPE_NAMES/ACTION_KINDS/DMG_LABELS/ST_LABELS 改双语;新增 LOGIC_OP_LABELS 并用于 _lop 下拉 |
wave_tab.gd |
TYPE_NAMES/BOSS_NAMES 改双语 |
resonance_tab.gd |
MATCH_LABELS 新增用于下拉;元素 A/B 改元素下拉 |
core_tab.gd |
TOPO/FEAT 归一为「中文 English」序(FEAT 补 3 项中文) |
status_tab.gd |
STACK 归一为「中文 English」序 |
其它运行时脚本、数据文件、其它 tab 逻辑不动。enemy_tab/balance_tab 仅受布局修复,文案不动。
9. 验证
validate_script四个改动文件全绿;reload_project+get_editor_errors无报错。- 回读往返测试(
execute_editor_script):- spell:逐条
_on_select→_read_metameta 一致(同上一特性);element_tags作为集合与原一致;含非元素自定义 tag 的情形自定义框保留。 - resonance:逐条
_on_select→ 重建 record,pattern(两元素)与match与原一致。
- spell:逐条
get_editor_screenshot目测:各页输入框撑满面板宽、下拉显示双语、法术页元素为复选框。
10. 范围外(YAGNI)
- 不改游戏运行时代码 / 数据文件格式 / 数据内容。
- 不动
enemy_tab.NAMES(持久化)与balance_tab中文标签。 - 不做元素标签之外的 tag 下拉词表(自定义框已覆盖)。
- resonance pattern 仍限两元素(现结构),不扩展多元素配方。
11. 验收标准
- 打开游戏设计器,各页输入框/下拉框随面板宽度撑满,长文本不再截断。
- 法术页「元素标签」为 5 个元素复选框 + 自定义框;
plasma_storm正确勾选 水+雷;保存后element_tags集合不变。 - 法术页 类型/动作种类/logic_op/伤害类型/施加状态 均双语显示,保存的
type/logic_op/damage_type等值不变。 - 波次页 类型/Boss、共鸣页 匹配方式 均双语;共鸣页 元素 A/B 为元素下拉,
resonance.json回读往返一致。 validate_script/reload_project无报错;spell 与 resonance 回读往返测试 FAILS=0。