Files
erqiwang_youle/client/js/01_SubGame/codes/config/Layout_CreateRoom.js
T
joywayerandClaude Opus 5 d1b60275a4 二七王:建房选项配置补精灵键、bit 统一挂到 item、补 || {} 保护声明
Sprites_CreateRoom.js 的注释说「配置里每个选项声明自己用哪个精灵键」,但 EQW_RoomOptions
的 items 只有 label/value,渲染器只剩「按下标拼字符串」一条路——而那正是同文件明文禁止的;
何况也拼不对(组的 key 是 'rules',精灵却叫 ROOM_BOX_RULE_1)。

- 每个类别加 titleSprite,每个选项加 box/text 精灵键,房卡附注加 noteSprite。
- bit 统一挂到每个 item 上(单选组各项写同一个 bit),拼 roomtype 的循环对
  radio/checkbox 是同一个形状(item → 写 value 到 bit),不再按组/项两种层级分支;
  checkbox 项补上 value:'1'。
- 补上其他常量文件都有的 `|| {}` 保护性声明。
- 守卫新增:精灵键必须存在且互不重复、必须恰好覆盖建房 View 预置的全部选项精灵、
  bit 不得再挂在组上、单选组内 bit 一致、多选组 bit 互异、位号刚好铺满 0–4
  (对齐服务端 class.config.js 的 IDX_ASET..IDX_NOCHECK)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 22:26:21 +08:00

120 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////
////////// EQW_Layout / EQW_RoomOptions: 建房规则选项(清单 §6.9b / §1.1)
///////////////////////////////////////////////////////////////
// 【纯数据文件】无函数、无副作用;依赖 LayoutConstants.js 先加载
// (引用其 EQW_Layout.TEXT_STYLE.*,属 EQW_Layout 内部自引用)。
var EQW_Layout = EQW_Layout || {};
//===== 建房规则选项区布局(清单 §6.9b)=====
//两层嵌套:类别竖排(ROOM_CATEGORY_COLUMN)+ 类别内选项槽横排(ROOM_OPTION_ROW)。
//本节数值按参考图比例估,实际以平台建房界面尺寸为准(清单 §6.9b 原文,不是本文件误差)。
//类别竖排。itemWidth 清单未给——类别行宽度等于平台内容区实际宽度,由调用方按实际面板尺寸注入。
//anchor 必须是竖排语义的 top/bottom/center:写成水平语义的 'left' 会被框架 switch 的 default
//当成居中(3 个类别时算出 y=[-56,-16,24],前两行跑到画布外),求解器现已按方向校验并抛错
EQW_Layout.ROOM_CATEGORY_COLUMN = {
kind: 'line', direction: 'vertical', anchorX: 0, anchorY: 0,
itemHeight: 32, spacing: 8, anchor: 'top',
runtime: ['itemWidth']
};
//类别标题:贴所在类别行。该行是 ROOM_CATEGORY_COLUMN 求解结果的第 N 项,不是固定精灵,
//target 由调用方按类别序号注入。资源 ROOM_CAT_TITLE 60×24(清单 §3)
EQW_Layout.ROOM_CATEGORY_TITLE = {
kind: 'attach', targetKind: 'layout', hAlign: 'left', vAlign: 'middle', offsetX: 0, w: 60, h: 24,
runtime: ['target']
};
//类别内选项槽横排。anchorY 清单未给(随所在类别行的 y 浮动,由调用方按该行位置注入);
//itemHeight 清单未给,沿用 ROOM_CATEGORY_COLUMN.itemHeight(同一行内选择框与文字纵向居中)
EQW_Layout.ROOM_OPTION_ROW = {
kind: 'line', direction: 'horizontal', anchorX: 70,
itemWidth: 150, itemHeight: EQW_Layout.ROOM_CATEGORY_COLUMN.itemHeight, spacing: 0, anchor: 'left',
runtime: ['anchorY']
};
//选项组之间的额外间隔(同类别下两个选项组之间比组内选项多留的间距)
EQW_Layout.ROOM_OPTION_GROUP_GAP = 40;
//选择框:贴所在选项槽左侧(资源 ROOM_OPT_BOX 22×22)。target 由调用方按选项槽注入
//(槽是 ROOM_OPTION_ROW 求解结果的第 N 项,故 targetKind 是 layout 而非精灵键)
EQW_Layout.ROOM_OPTION_BOX = {
kind: 'attach', targetKind: 'layout', hAlign: 'left', vAlign: 'middle', w: 22, h: 22,
runtime: ['target']
};
//选项文字:贴同槽选择框右侧(target 是该槽的 ROOM_BOX_* 精灵,由调用方按选项配置的 box 键注入),
//纯文字,清单未给宽高,由调用方按渲染出的文案尺寸注入。
//选中态变橙见 EQW_Layout.TEXT_STYLE.ROOM_OPT(normal / selected 两态,由调用方按选中状态二选一)
EQW_Layout.ROOM_OPTION_TEXT = {
kind: 'attach', targetKind: 'sprite', hAlign: 'right', vAlign: 'middle', offsetX: 8,
runtime: ['target', 'w', 'h']
};
//房卡附注:贴扣卡组最后一个选项(固定精灵 ROOM_BOX_CARD_2)右侧。纯文字,宽高随文案运行时注入
EQW_Layout.ROOM_CARD_COST_NOTE = {
kind: 'attach', targetKind: 'sprite', target: 'ROOM_BOX_CARD_2',
hAlign: 'right', vAlign: 'middle', offsetX: 20,
textStyle: EQW_Layout.TEXT_STYLE.ROOM_CARD_COST_NOTE,
runtime: ['w', 'h']
};
//折行:选项数超过 maxPerRow 时改用 grid。二七王每组最多 2 项,不会触发(清单 §6.9b 原文);
//清单原文是 grid{cols:maxPerRow, spacingX:0, spacingY:8, fillOrder:'row'},cols 直接取自 maxPerRow,
//故与 spacingX/spacingY/fillOrder 一并记为已定的四个字段。
//rows 由实际选项数决定(ceil(选项数 / cols)),anchorX/anchorY 随所在类别行浮动 —— 三者都是运行时值,
//在 runtime 里显式声明;缺 rows 时求解器会抛错,不再静默返回空数组(一个矩形都不产出)。
//itemWidth / itemHeight 清单同样未给:折行摆的还是同一批选项槽,沿用 ROOM_OPTION_ROW 的槽尺寸,
//不另编一套数值;anchor 同理沿用 ROOM_OPTION_ROW 的 'left'(折行前后左边缘对齐一致)
EQW_Layout.ROOM_OPTION_MAX_PER_ROW = 4;
EQW_Layout.ROOM_OPTION_OVERFLOW_GRID = {
kind: 'grid', cols: EQW_Layout.ROOM_OPTION_MAX_PER_ROW, spacingX: 0, spacingY: 8, fillOrder: 'row',
itemWidth: EQW_Layout.ROOM_OPTION_ROW.itemWidth, itemHeight: EQW_Layout.ROOM_OPTION_ROW.itemHeight,
anchor: 'left',
runtime: ['rows', 'anchorX', 'anchorY']
};
///////////////////////////////////////////////////////////////
////////// EQW_RoomOptions: 建房规则选项配置(清单 §1.1)///////
///////////////////////////////////////////////////////////////
//整个界面由本配置驱动渲染,加一个选项 = 配置里加一条,不改渲染逻辑(工程总则 §5 OCP / §6 配置优先)。
//type: 'radio' 单选 / 'checkbox' 多选 / 'radioOptional' 单选可不选
//选择框帧号 = (useCheckbox ? 3 : 1) + (selected ? 1 : 0),useCheckbox = (checkbox 或 radioOptional)
//
//【精灵键由配置给出】每个类别声明自己的标题精灵 titleSprite,每个选项声明自己的选择框精灵 box
//与文字精灵 text,附注声明 noteSprite——渲染器一律按键名取精灵,【不得按下标拼字符串】
//(组的 key 是 'rules'、精灵却叫 ROOM_BOX_RULE_1,本来就拼不出来)。
//
//【roomtype 拼串只在一处实现】拼串就是遍历本配置,不得在别处按下标硬拼
//(与服务端 class.config.js parse() 对称的 SSOT 要求)。bit/value 统一挂在【每个 item 上】:
// - radio:组内各 item 写同一个 bit,选中哪个就把该 item 的 value 写进该位;
// - checkbox:勾选写 item.value、不勾写 '0'。
//这样拼串循环对两种 type 是同一个形状(item → 写 value 到 bit),不必按组/项两种层级分支
var EQW_RoomOptions = EQW_RoomOptions || {
categories: [
{ titleFrame: 1, titleSprite: 'ROOM_CAT_TITLE_1', /* 牌局 */ groups: [
{ key: 'aset', type: 'radio',
items: [ { label: '6局', value: '0', bit: 0, box: 'ROOM_BOX_ASET_1', text: 'ROOM_TEXT_ASET_1' },
{ label: '12局', value: '1', bit: 0, box: 'ROOM_BOX_ASET_2', text: 'ROOM_TEXT_ASET_2' } ] },
{ key: 'card', type: 'radio', note: 'cardCost', noteSprite: 'ROOM_TEXT_CARD_COST',
items: [ { label: '房主扣卡', value: '0', bit: 1, box: 'ROOM_BOX_CARD_1', text: 'ROOM_TEXT_CARD_1' },
{ label: 'AA每人扣卡', value: '1', bit: 1, box: 'ROOM_BOX_CARD_2', text: 'ROOM_TEXT_CARD_2' } ] }
] },
{ titleFrame: 2, titleSprite: 'ROOM_CAT_TITLE_2', /* 模式 */ groups: [
{ key: 'peek', type: 'radio',
items: [ { label: '可查牌', value: '0', bit: 4, box: 'ROOM_BOX_PEEK_1', text: 'ROOM_TEXT_PEEK_1' },
{ label: '不查牌', value: '1', bit: 4, box: 'ROOM_BOX_PEEK_2', text: 'ROOM_TEXT_PEEK_2' } ] }
] },
{ titleFrame: 3, titleSprite: 'ROOM_CAT_TITLE_3', /* 规则 */ groups: [
{ key: 'rules', type: 'checkbox',
items: [ { label: '傍王', value: '1', bit: 2, box: 'ROOM_BOX_RULE_1', text: 'ROOM_TEXT_RULE_1' },
{ label: '爬坡', value: '1', bit: 3, box: 'ROOM_BOX_RULE_2', text: 'ROOM_TEXT_RULE_2' } ] }
] }
],
//房卡消耗联动(协议 §0.5):不硬编码在 UI 代码里
cardCost: {
'0': { '0': '房主2张', '1': '房主4张' }, //房主扣卡:6局 / 12局
'1': { '0': '每人1张', '1': '每人2张' } //AA 每人扣卡:6局 / 12局
}
};