From c0782169e2151c2456f71bea38c0b579f2637f46 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 28 Sep 2025 23:37:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=BB=98=E8=AE=A4=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client-modules/src/render/shared.ts | 2 +- .../client-modules/src/render/ui/main.tsx | 24 +- .../src/render/ui/statusBar.tsx | 478 ++++++++++++++---- .../client-modules/src/render/ui/toolbar.tsx | 2 - public/_server/table/data.comment.js | 14 +- public/project/data.js | 6 +- 6 files changed, 413 insertions(+), 113 deletions(-) diff --git a/packages-user/client-modules/src/render/shared.ts b/packages-user/client-modules/src/render/shared.ts index 11b5516..32626af 100644 --- a/packages-user/client-modules/src/render/shared.ts +++ b/packages-user/client-modules/src/render/shared.ts @@ -29,7 +29,7 @@ export const STATUS_BAR_HEIGHT = 32 * MAP_BLOCK_HEIGHT; /** 右侧状态栏的横坐标 */ export const RIGHT_STATUS_POS = STATUS_BAR_WIDTH + MAP_WIDTH; /** 是否启用右侧状态栏 */ -export const ENABLE_RIGHT_STATUS_BAR = true; +export const ENABLE_RIGHT_STATUS_BAR = false; /** 状态栏数量,启用右侧状态栏为两个,不启用为一个 */ export const STATUS_BAR_COUNT = ENABLE_RIGHT_STATUS_BAR ? 2 : 1; /** 状态栏宽度的一半 */ diff --git a/packages-user/client-modules/src/render/ui/main.tsx b/packages-user/client-modules/src/render/ui/main.tsx index 0af8047..50c4cf8 100644 --- a/packages-user/client-modules/src/render/ui/main.tsx +++ b/packages-user/client-modules/src/render/ui/main.tsx @@ -108,14 +108,25 @@ const MainScene = defineComponent(() => { }); const leftStatus: ILeftHeroStatus = reactive({ hp: 0, + hpmax: 0, + mana: 0, + manamax: 0, atk: 0, def: 0, mdef: 0, money: 0, exp: 0, + up: 0, yellowKey: 0, blueKey: 0, redKey: 0, + greenKey: 0, + pickaxe: 0, + bomb: 0, + centerFly: 0, + poison: false, + weak: false, + curse: false, floor: 'MT0', lv: '', replay: replayStatus @@ -132,13 +143,24 @@ const MainScene = defineComponent(() => { const hero = core.status.hero; leftStatus.atk = getHeroStatusOn('atk'); leftStatus.hp = getHeroStatusOn('hp'); + leftStatus.hpmax = getHeroStatusOn('hpmax'); + leftStatus.mana = getHeroStatusOn('mana'); + leftStatus.manamax = getHeroStatusOn('manamax'); leftStatus.def = getHeroStatusOn('def'); leftStatus.mdef = getHeroStatusOn('mdef'); leftStatus.money = getHeroStatusOn('money'); - leftStatus.exp = core.getNextLvUpNeed() ?? 0; + leftStatus.exp = getHeroStatusOn('exp'); + leftStatus.up = core.getNextLvUpNeed() ?? 0; leftStatus.yellowKey = core.itemCount('yellowKey'); leftStatus.blueKey = core.itemCount('blueKey'); leftStatus.redKey = core.itemCount('redKey'); + leftStatus.greenKey = core.itemCount('greenKey'); + leftStatus.pickaxe = core.itemCount('pickaxe'); + leftStatus.bomb = core.itemCount('bomb'); + leftStatus.centerFly = core.itemCount('centerFly'); + leftStatus.poison = core.getFlag('poison', true); + leftStatus.weak = core.getFlag('weak', true); + leftStatus.curse = core.getFlag('curse', true); leftStatus.floor = core.status.floorId; leftStatus.lv = core.getLvName(hero.lv); diff --git a/packages-user/client-modules/src/render/ui/statusBar.tsx b/packages-user/client-modules/src/render/ui/statusBar.tsx index 779d7b8..07bdd29 100644 --- a/packages-user/client-modules/src/render/ui/statusBar.tsx +++ b/packages-user/client-modules/src/render/ui/statusBar.tsx @@ -1,29 +1,68 @@ import { GameUI, SetupComponentOptions } from '@motajs/system-ui'; -import { computed, defineComponent, ref } from 'vue'; +import { computed, ComputedRef, defineComponent, shallowReactive } from 'vue'; import { TextContent } from '../components'; -import { DefaultProps, ElementLocator, Font } from '@motajs/render'; import { - NumpadToolbar, - PlayingToolbar, - ReplayingStatus, - ReplayingToolbar -} from './toolbar'; + DefaultProps, + ElementLocator, + Font, + SizedCanvasImageSource +} from '@motajs/render'; +import { MixedToolbar, ReplayingStatus } from './toolbar'; import { openViewMap } from './viewmap'; import { mainUIController } from './controller'; -import { MAIN_HEIGHT, STATUS_BAR_WIDTH } from '../shared'; +import { + MAIN_HEIGHT, + MAIN_WIDTH, + STATUS_BAR_HEIGHT, + STATUS_BAR_WIDTH +} from '../shared'; export interface ILeftHeroStatus { - hp: number; - atk: number; - def: number; - mdef: number; - money: number; - exp: number; - yellowKey: number; - blueKey: number; - redKey: number; + /** 楼层 id */ floor: FloorIds; + /** 等级名称 */ lv: string; + /** 生命值 */ + hp: number; + /** 生命上限 */ + hpmax: number; + /** 魔力值 */ + mana: number; + /** 魔力上限 */ + manamax: number; + /** 攻击力 */ + atk: number; + /** 防御力 */ + def: number; + /** 魔防(护盾) */ + mdef: number; + /** 金币 */ + money: number; + /** 经验值 */ + exp: number; + /** 距离升级剩余经验 */ + up: number; + /** 黄钥匙数量 */ + yellowKey: number; + /** 蓝钥匙数量 */ + blueKey: number; + /** 红钥匙数量 */ + redKey: number; + /** 绿钥匙数量 */ + greenKey: number; + /** 破数量 */ + pickaxe: number; + /** 炸数量 */ + bomb: number; + /** 飞数量 */ + centerFly: number; + /** 是否中毒 */ + poison: boolean; + /** 是否中衰 */ + weak: boolean; + /** 是否中咒 */ + curse: boolean; + /** 录像状态 */ replay: ReplayingStatus; } @@ -32,6 +71,31 @@ export interface IRightHeroStatus { exampleHard: number; } +interface StatusInfo { + /** 图标 */ + icon: SizedCanvasImageSource; + /** 属性值,经过格式化 */ + value: ComputedRef; + /** 字体 */ + font: Font; + /** 文字颜色 */ + color: CanvasStyle; +} + +interface KeyLikeItem { + /** 属性值,经过格式化 */ + value: ComputedRef; + /** 字体 */ + font: Font; + /** 文字颜色 */ + color: CanvasStyle; +} + +interface KeyLikeInfo { + /** 这一行包含的内容 */ + items: KeyLikeItem[]; +} + interface StatusBarProps extends DefaultProps { loc: ElementLocator; status: T; @@ -44,96 +108,336 @@ const statusBarProps = { export const LeftStatusBar = defineComponent>( p => { - const hpIcon = core.material.images.images['hp.png']; - const atkIcon = core.material.images.images['atk.png']; - const defIcon = core.material.images.images['def.png']; - const mdefIcon = core.material.images.images['IQ.png']; - const moneyIcon = core.material.images.images['money.png']; - const expIcon = core.material.images.images['exp.png']; + //#region 参数定义 + + /** 属性文字的横坐标 */ + const TEXT_X = 54; + /** 图标的横坐标 */ + const STATUS_PAD = 8; + /** 楼层名称的高度 */ + const TITLE_HEIGHT = 36; + /** 状态属性的开始纵坐标 */ + const STATUS_Y = TITLE_HEIGHT + STATUS_PAD; + + // 可以换成 core.material.images.images['xxx.png'] 来使用全塔属性注册的图片 + const hpIcon = core.statusBar.icons.hp; + const atkIcon = core.statusBar.icons.atk; + const defIcon = core.statusBar.icons.def; + const mdefIcon = core.statusBar.icons.mdef; + const moneyIcon = core.statusBar.icons.money; + const expIcon = core.statusBar.icons.exp; + const manaIcon = core.statusBar.icons.mana; + const lvIcon = core.statusBar.icons.lv; const s = p.status; - const f = core.formatBigNumber; - const inNumpad = ref(false); + /** 常规字体 */ + const font1 = Font.defaults({ size: 18 }); + /** 加粗字体 */ + const font2 = Font.defaults({ size: 18, weight: 700 }); + /** 楼层名 */ const floorName = computed(() => core.floors[s.floor]?.title ?? ''); + /** 钥匙显示文字 */ const key = (num: number) => { return num.toString().padStart(2, '0'); }; - const onNumpad = () => { - inNumpad.value = !inNumpad.value; - }; + //#region 属性显示 - const font1 = Font.defaults({ size: 18 }); - const font2 = Font.defaults({ size: 18, weight: 700 }); + /** 一般属性 */ + const statusInfo: StatusInfo[] = shallowReactive([]); + /** 钥匙属性 */ + const keyLike: KeyLikeInfo[] = shallowReactive([]); - const iconLoc = (n: number): ElementLocator => { - return [16, 76 + 44 * n, 32, 32]; - }; + // 根据全塔属性配置显示属性 + // 如果你想修改状态栏显示,不建议修改这里的内容,而建议直接新增标签 + // 这里的内容是为使用样板默认状态栏的人准备的,对于新增属性来说过于复杂,而且功能有限,对于新手来说也难以理解 + // 可以参考说明文档中的常见需求指南中的新增状态教程 - const textLoc = (n: number): ElementLocator => { - return [60, 92 + 44 * n, void 0, void 0, 0, 0.5]; - }; + const list = core.flags.statusBarItems; + // 等级 + if (list.includes('enableLv')) { + statusInfo.push({ + icon: lvIcon, + value: computed(() => s.lv), + font: font1, + color: '#fff' + }); + } + + // 生命值 + if (list.includes('enableHP')) { + if (list.includes('enableHPMax')) { + // 如果启用血限 + statusInfo.push({ + icon: hpIcon, + value: computed(() => { + const hp = core.formatBigNumber(s.hp); + const hpmax = core.formatBigNumber(s.hpmax); + return `${hp} / ${hpmax}`; + }), + font: font1, + color: '#fff' + }); + } else { + // 如果禁用血限 + statusInfo.push({ + icon: hpIcon, + value: computed(() => core.formatBigNumber(s.hp)), + font: font1, + color: '#fff' + }); + } + } + + // 魔力 + if (list.includes('enableMana')) { + statusInfo.push({ + icon: manaIcon, + value: computed(() => { + const mana = core.formatBigNumber(s.mana); + const manamax = core.formatBigNumber(s.manamax); + if (s.manamax > 0) { + // 如果启用魔力上限 + return `${mana} / ${manamax}`; + } else { + // 如果禁用魔力上限 + return mana; + } + }), + font: font1, + color: '#fff' + }); + } + + // 攻击力 + if (list.includes('enableAtk')) { + statusInfo.push({ + icon: atkIcon, + value: computed(() => core.formatBigNumber(s.atk)), + font: font1, + color: '#fff' + }); + } + + // 防御力 + if (list.includes('enableDef')) { + statusInfo.push({ + icon: defIcon, + value: computed(() => core.formatBigNumber(s.def)), + font: font1, + color: '#fff' + }); + } + + // 魔防(护盾) + if (list.includes('enableMdef')) { + statusInfo.push({ + icon: mdefIcon, + value: computed(() => core.formatBigNumber(s.mdef)), + font: font1, + color: '#fff' + }); + } + + // 金币 + if (list.includes('enableMoney')) { + statusInfo.push({ + icon: moneyIcon, + value: computed(() => core.formatBigNumber(s.money)), + font: font1, + color: '#fff' + }); + } + + // 经验值 + if (list.includes('enableExp')) { + if (list.includes('enableLevelUp')) { + // 升级模式 + statusInfo.push({ + icon: expIcon, + value: computed(() => core.formatBigNumber(s.up)), + font: font1, + color: '#fff' + }); + } else { + // 非升级模式 + statusInfo.push({ + icon: expIcon, + value: computed(() => core.formatBigNumber(s.exp)), + font: font1, + color: '#fff' + }); + } + } + + // 钥匙 + if (list.includes('enableKeys')) { + const keys: KeyLikeItem[] = []; + keyLike.push({ items: keys }); + // 黄钥匙 + keys.push({ + value: computed(() => key(s.yellowKey)), + font: font2, + color: '#fca' + }); + // 蓝钥匙 + keys.push({ + value: computed(() => key(s.blueKey)), + font: font2, + color: '#aad' + }); + // 红钥匙 + keys.push({ + value: computed(() => key(s.redKey)), + font: font2, + color: '#f88' + }); + // 绿钥匙 + if (list.includes('enableGreenKey')) { + keys.push({ + value: computed(() => key(s.greenKey)), + font: font2, + color: '#8f8' + }); + } + } + + // 破炸飞 + if (list.includes('enablePZF')) { + const items: KeyLikeItem[] = []; + keyLike.push({ items }); + items.push({ + value: computed(() => `破 ${s.pickaxe}`), + font: font1, + color: '#bc6e27' + }); + items.push({ + value: computed(() => `炸 ${s.bomb}`), + font: font1, + color: '#fa14b9' + }); + items.push({ + value: computed(() => `飞 ${s.centerFly}`), + font: font1, + color: '#8db600' + }); + } + + // 毒衰咒 + if (list.includes('enableDebuff')) { + const debuffs: KeyLikeItem[] = []; + keyLike.push({ items: debuffs }); + debuffs.push({ + value: computed(() => (s.poison ? '毒' : '')), + font: font1, + color: '#affca8' + }); + debuffs.push({ + value: computed(() => (s.weak ? '衰' : '')), + font: font1, + color: '#feccd0' + }); + debuffs.push({ + value: computed(() => (s.curse ? '咒' : '')), + font: font1, + color: '#c2f4e7' + }); + } + + //#region 布局控制 + + /** 用于显示状态的高度,高度=状态栏高度-工具栏高度-楼层名高度-填充高度 */ + const statusHeight = + STATUS_BAR_HEIGHT - 113 - TITLE_HEIGHT - STATUS_PAD * 2; + + /** 每一行的高度 */ + const rowHeight = computed(() => { + const length = statusInfo.length + keyLike.length; + return statusHeight / length; + }); + /** 钥匙、破炸飞、毒衰咒开始显示的纵坐标 */ + const keyStart = computed(() => { + const statusHeight = statusInfo.length * rowHeight.value; + return STATUS_Y + statusHeight; + }); + + /** + * 左右居中布局 + * @param y 纵坐标 + */ const central = (y: number): ElementLocator => { const width = p.loc[2] ?? 200; return [width / 2, y, void 0, void 0, 0.5, 0.5]; }; - const keyCount = 3; - const keyY = 92 + 44 * 6; - const keyLoc = (n: number): ElementLocator => { - const width = p.loc[2] ?? 200; - const per = width / (keyCount + 1); - return [per * (n + 1), keyY, void 0, void 0, 0.5, 0.5]; - }; - + /** + * 点击楼层名打开浏览地图 + */ const viewMap = () => { - openViewMap(mainUIController, [0, 0, 840, 480]); + openViewMap(mainUIController, [0, 0, MAIN_WIDTH, MAIN_HEIGHT]); }; return () => ( ); }, diff --git a/packages-user/client-modules/src/render/ui/toolbar.tsx b/packages-user/client-modules/src/render/ui/toolbar.tsx index c4d3e64..dd3c490 100644 --- a/packages-user/client-modules/src/render/ui/toolbar.tsx +++ b/packages-user/client-modules/src/render/ui/toolbar.tsx @@ -155,8 +155,6 @@ export interface ReplayingStatus { played: number; /** 总长度 */ total: number; - /** 是否是录像模式 */ - replaying: boolean; } export interface ReplayingProps extends ToolbarProps { diff --git a/public/_server/table/data.comment.js b/public/_server/table/data.comment.js index c685c78..202b620 100644 --- a/public/_server/table/data.comment.js +++ b/public/_server/table/data.comment.js @@ -528,9 +528,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "checkboxSet", "_checkboxSet": { "prefix": [ - "楼层", - "名字", - "
等级", + "等级", "血限", "
生命", "魔力", @@ -540,16 +538,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "金币", "
经验", "升级", - "
升级扣除模式", "
钥匙", "绿钥", "
破炸", - "负面", - "
技能" + "负面" ], "key": [ - "enableFloor", - "enableName", "enableLv", "enableHPMax", "enableHP", @@ -560,12 +554,10 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "enableMoney", "enableExp", "enableLevelUp", - "levelUpLeftMode", "enableKeys", "enableGreenKey", "enablePZF", - "enableDebuff", - "enableSkill" + "enableDebuff" ] }, "_data": "状态栏显示项" diff --git a/public/project/data.js b/public/project/data.js index cdcac4d..96b1d5a 100644 --- a/public/project/data.js +++ b/public/project/data.js @@ -803,16 +803,12 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = }, "flags": { "statusBarItems": [ - "enableFloor", - "enableLv", "enableHP", "enableAtk", "enableDef", "enableMDef", "enableMoney", "enableExp", - "enableLevelUp", - "levelUpLeftMode", "enableKeys" ], "flyNearStair": false, @@ -836,7 +832,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "enableRouteFolding": true, "disableShopOnDamage": false, "blurFg": true, - "extendToolbar": true, + "extendToolbar": false, "enableEnemyPoint": null, "autoScale": true }