From d175f6682bdd2fdf7934e37721d2bd4a763045bc Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 28 Sep 2025 16:25:53 +0800 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20=E5=8F=B3=E4=BE=A7=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=A0=8F=E6=94=B9=E4=B8=BA=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/render/components/textboxTyper.ts | 2 +- .../client-modules/src/render/ui/main.tsx | 57 +-- .../src/render/ui/statusBar.tsx | 326 +++--------------- .../client-modules/src/render/ui/toolbar.tsx | 2 + 4 files changed, 67 insertions(+), 320 deletions(-) diff --git a/packages-user/client-modules/src/render/components/textboxTyper.ts b/packages-user/client-modules/src/render/components/textboxTyper.ts index 1e5456b..5a21f97 100644 --- a/packages-user/client-modules/src/render/components/textboxTyper.ts +++ b/packages-user/client-modules/src/render/components/textboxTyper.ts @@ -1021,7 +1021,7 @@ export class TextContentParser { this.blocks.forEach(v => { if (v.type !== TextContentType.Wait) { width += v.width; - height = v.height; + if (v.height > height) height = v.height; } }); const line: ITextContentLine = { diff --git a/packages-user/client-modules/src/render/ui/main.tsx b/packages-user/client-modules/src/render/ui/main.tsx index 055ba98..0af8047 100644 --- a/packages-user/client-modules/src/render/ui/main.tsx +++ b/packages-user/client-modules/src/render/ui/main.tsx @@ -36,8 +36,7 @@ import { RightStatusBar } from './statusBar'; import { ReplayingStatus } from './toolbar'; -import { getHeroStatusOn, HeroSkill, NightSpecial } from '@user/data-state'; -import { jumpIgnoreFloor } from '@user/legacy-plugin-data'; +import { getHeroStatusOn } from '@user/data-state'; import { hook } from '@user/data-base'; import { FloorDamageExtends, FloorItemDetail } from '../elements'; import { LayerGroupPortal } from '../legacy/portal'; @@ -100,6 +99,13 @@ const MainScene = defineComponent(() => { } }); + const replayStatus: ReplayingStatus = reactive({ + replaying: false, + playing: false, + speed: 1, + played: 0, + total: 0 + }); const leftStatus: ILeftHeroStatus = reactive({ hp: 0, atk: 0, @@ -112,26 +118,10 @@ const MainScene = defineComponent(() => { redKey: 0, floor: 'MT0', lv: '', - regen: 0, - exAtk: 0, - magicDef: 0 - }); - const replayStatus: ReplayingStatus = reactive({ - playing: false, - speed: 1, - played: 0, - total: 0 + replay: replayStatus }); const rightStatus: IRightHeroStatus = reactive({ - autoSkill: false, - skillName: '', - skillDesc: '', - jumpCount: 0, - springCount: 0, - floor: 'MT0', - replaying: false, - replayStatus, - night: 0 + exampleHard: 0 }); //#region 状态更新 @@ -140,7 +130,6 @@ const MainScene = defineComponent(() => { hideStatus.value = core.getFlag('hideStatusBar', false); const hero = core.status.hero; - const floor = core.status.floorId; leftStatus.atk = getHeroStatusOn('atk'); leftStatus.hp = getHeroStatusOn('hp'); leftStatus.def = getHeroStatusOn('def'); @@ -152,35 +141,15 @@ const MainScene = defineComponent(() => { leftStatus.redKey = core.itemCount('redKey'); leftStatus.floor = core.status.floorId; leftStatus.lv = core.getLvName(hero.lv); - leftStatus.regen = getHeroStatusOn('hpmax'); - leftStatus.exAtk = getHeroStatusOn('mana'); - leftStatus.magicDef = getHeroStatusOn('magicDef'); - rightStatus.autoSkill = HeroSkill.getAutoSkill(); - rightStatus.skillName = HeroSkill.getSkillName(); - rightStatus.skillDesc = HeroSkill.getSkillDesc(); - rightStatus.night = NightSpecial.getNight(floor); - rightStatus.floor = floor; - rightStatus.replaying = core.isReplaying(); const { pausing, speed, toReplay, totalList } = core.status.replay; + replayStatus.replaying = core.isReplaying(); replayStatus.playing = !pausing; replayStatus.speed = speed; replayStatus.played = totalList.length - toReplay.length; replayStatus.total = totalList.length; - if (HeroSkill.learnedSkill(HeroSkill.Jump)) { - if (jumpIgnoreFloor.has(floor)) { - rightStatus.jumpCount = -2; - } else { - rightStatus.jumpCount = 3 - (flags[`jump_${floor}`] ?? 0); - } - } else { - rightStatus.jumpCount = -1; - } - if (core.hasFlag('spring')) { - rightStatus.springCount = 50 - (flags.springCount ?? 0); - } else { - rightStatus.springCount = -1; - } + + rightStatus.exampleHard = flags.hard; }; const updateDataFallback = () => { diff --git a/packages-user/client-modules/src/render/ui/statusBar.tsx b/packages-user/client-modules/src/render/ui/statusBar.tsx index 03f3529..779d7b8 100644 --- a/packages-user/client-modules/src/render/ui/statusBar.tsx +++ b/packages-user/client-modules/src/render/ui/statusBar.tsx @@ -1,26 +1,16 @@ import { GameUI, SetupComponentOptions } from '@motajs/system-ui'; -import { computed, defineComponent, ref, watch } from 'vue'; +import { computed, defineComponent, ref } from 'vue'; import { TextContent } from '../components'; -import { - DefaultProps, - ElementLocator, - Sprite, - Font, - MotaOffscreenCanvas2D -} from '@motajs/render'; -import { transitionedColor } from '../use'; -import { linear } from 'mutate-animate'; -import { Scroll } from '../components'; -import { getArea, MinimapDrawer } from '@motajs/legacy-ui'; +import { DefaultProps, ElementLocator, Font } from '@motajs/render'; import { NumpadToolbar, PlayingToolbar, ReplayingStatus, ReplayingToolbar } from './toolbar'; -import { HeroSkill } from '@user/data-state'; import { openViewMap } from './viewmap'; import { mainUIController } from './controller'; +import { MAIN_HEIGHT, STATUS_BAR_WIDTH } from '../shared'; export interface ILeftHeroStatus { hp: number; @@ -34,33 +24,12 @@ export interface ILeftHeroStatus { redKey: number; floor: FloorIds; lv: string; - /** 生命回复 */ - regen: number; - /** 额外攻击 */ - exAtk: number; - /** 魔法防御 */ - magicDef: number; + replay: ReplayingStatus; } export interface IRightHeroStatus { - /** 自动切换技能 */ - autoSkill: boolean; - /** 当前开启的技能 */ - skillName: string; - /** 技能描述 */ - skillDesc: string; - /** 跳跃剩余次数,-1 表示未开启,-2表示当前楼层不能跳 */ - jumpCount: number; - /** 治愈之泉剩余次数,-1 表示未开启 */ - springCount: number; - /** 当前楼层 */ - floor: FloorIds; - /** 是否正在录像播放 */ - replaying: boolean; - /** 录像播放状态 */ - replayStatus: ReplayingStatus; - /** 极昼永夜 */ - night: number; + /** 示例属性,以游戏难度作为示例 */ + exampleHard: number; } interface StatusBarProps extends DefaultProps { @@ -85,15 +54,20 @@ export const LeftStatusBar = defineComponent>( const s = p.status; const f = core.formatBigNumber; + const inNumpad = ref(false); + const floorName = computed(() => core.floors[s.floor]?.title ?? ''); const key = (num: number) => { return num.toString().padStart(2, '0'); }; + const onNumpad = () => { + inNumpad.value = !inNumpad.value; + }; + const font1 = Font.defaults({ size: 18 }); const font2 = Font.defaults({ size: 18, weight: 700 }); - const font3 = Font.defaults({ size: 14, weight: 700 }); const iconLoc = (n: number): ElementLocator => { return [16, 76 + 44 * n, 32, 32]; @@ -108,11 +82,6 @@ export const LeftStatusBar = defineComponent>( return [width / 2, y, void 0, void 0, 0.5, 0.5]; }; - const right = (y: number): ElementLocator => { - const width = p.loc[2] ?? 200; - return [width - 16, y, void 0, void 0, 1, 0.5]; - }; - const keyCount = 3; const keyY = 92 + 44 * 6; const keyLoc = (n: number): ElementLocator => { @@ -137,30 +106,10 @@ export const LeftStatusBar = defineComponent>( - - - {s.magicDef > 0 && ( - - )} @@ -185,232 +134,59 @@ export const LeftStatusBar = defineComponent>( font={font2} fillStyle="#f88" > - - + + {inNumpad.value ? ( + + ) : s.replay.replaying ? ( + + ) : ( + + )} ); }, statusBarProps ); -interface RightStatusBarMisc { - name: string; - value: string; - nameColor: string; - valueColor: string; -} - export const RightStatusBar = defineComponent>( p => { - const font1 = new Font('normal', 18); - const font2 = new Font('normal', 16); + // p.status 就是你在 main.tsx 中传入的属性内容,用法与左侧状态栏完全一致 - const minimap = ref(); - const inNumpad = ref(false); - - const onNumpad = () => { - inNumpad.value = !inNumpad.value; - }; - - const s = p.status; - const skill = computed(() => - s.autoSkill ? '已开启自动切换' : s.skillName - ); - const skillDesc = computed(() => - s.autoSkill ? '自动切换技能时,会自动选择最优技能' : s.skillDesc - ); - - const skillColor = transitionedColor('#284', 200, linear())!; - - watch( - () => s.autoSkill, - value => { - skillColor.set(value ? '#284' : '#824'); - } - ); - - const miscData = computed(() => { - const data: RightStatusBarMisc[] = []; - if (s.jumpCount !== -1) { - const text = - s.jumpCount === -2 ? '不可跳跃' : s.jumpCount.toString(); - data.push({ - name: '跳跃剩余', - nameColor: '#fff', - value: text, - valueColor: '#fff' - }); - } - if (s.springCount >= 0) { - data.push({ - name: '治愈之泉', - nameColor: '#a7ffa7', - value: s.springCount.toString(), - valueColor: '#a7ffa7' - }); - } - if (s.night !== 0) { - const text = s.night.toString(); - data.push({ - name: '极昼永夜', - nameColor: '#a3f8ff', - value: s.night > 0 ? '+' + text : text, - valueColor: s.night > 0 ? '#a7ffa7' : '#ffa7a7' - }); - } - return data; - }); - - const central = (y: number): ElementLocator => { - const width = p.loc[2] ?? 200; - return [width / 2, y, void 0, void 0, 0.5, 0.5]; - }; - - const middle = (x: number, y: number): ElementLocator => { - return [x, y, void 0, void 0, 0, 0.5]; - }; - - const changeAutoSkill = () => { - const auto = !s.autoSkill; - HeroSkill.setAutoSkill(auto); - core.status.route.push(`set:autoSkill:${auto}`); - core.updateStatusBar(); - }; - - const area = getArea(); - const minimapDrawer = new MinimapDrawer( - document.createElement('canvas') - ); - minimapDrawer.noBorder = true; - minimapDrawer.scale = 4; - minimapDrawer.showInfo = true; - let linked = false; - const drawMinimap = (canvas: MotaOffscreenCanvas2D) => { - const ctx = canvas.ctx; - ctx.scale( - 1 / core.domStyle.scale / devicePixelRatio, - 1 / core.domStyle.scale / devicePixelRatio - ); - if (!linked) { - minimapDrawer.link(canvas.canvas); - linked = true; - } - if (minimapDrawer.nowFloor !== s.floor) { - minimapDrawer.drawedThumbnail = {}; - } else { - minimapDrawer.drawToTarget(); - ctx.restore(); - return; - } - minimapDrawer.nowFloor = s.floor; - minimapDrawer.nowArea = - Object.keys(area).find(v => - area[v].includes(core.status.floorId) - ) ?? ''; - minimapDrawer.locateMap(minimapDrawer.nowFloor); - minimapDrawer.drawMap(); - }; - - watch( - () => s.floor, - () => { - minimap.value?.update(); - } - ); + const text = `这里是右侧状态栏,如果左侧状态栏不够用可以在 \\r[gold]statusBar.tsx\\r 中编写内容,如果不需要此状态栏,可以在 \\r[gold]shared.ts\\r 中关闭此状态栏。`; return () => { return ( ); }; diff --git a/packages-user/client-modules/src/render/ui/toolbar.tsx b/packages-user/client-modules/src/render/ui/toolbar.tsx index c7155e6..536b5f5 100644 --- a/packages-user/client-modules/src/render/ui/toolbar.tsx +++ b/packages-user/client-modules/src/render/ui/toolbar.tsx @@ -153,6 +153,8 @@ export interface ReplayingStatus { played: number; /** 总长度 */ total: number; + /** 是否是录像模式 */ + replaying: boolean; } export interface ReplayingProps extends ToolbarProps { From 415dd1d8c9eeb64b704cfb118855c5604a274470 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 28 Sep 2025 16:25:53 +0800 Subject: [PATCH 2/4] =?UTF-8?q?chore:=20=E5=8F=B3=E4=BE=A7=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=A0=8F=E6=94=B9=E4=B8=BA=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client-modules/src/render/ui/main.tsx | 55 +--- .../src/render/ui/statusBar.tsx | 310 ++++-------------- .../client-modules/src/render/ui/toolbar.tsx | 2 + 3 files changed, 69 insertions(+), 298 deletions(-) diff --git a/packages-user/client-modules/src/render/ui/main.tsx b/packages-user/client-modules/src/render/ui/main.tsx index fcd5ac9..0af8047 100644 --- a/packages-user/client-modules/src/render/ui/main.tsx +++ b/packages-user/client-modules/src/render/ui/main.tsx @@ -36,8 +36,7 @@ import { RightStatusBar } from './statusBar'; import { ReplayingStatus } from './toolbar'; -import { getHeroStatusOn, HeroSkill, NightSpecial } from '@user/data-state'; -import { jumpIgnoreFloor } from '@user/legacy-plugin-data'; +import { getHeroStatusOn } from '@user/data-state'; import { hook } from '@user/data-base'; import { FloorDamageExtends, FloorItemDetail } from '../elements'; import { LayerGroupPortal } from '../legacy/portal'; @@ -100,6 +99,13 @@ const MainScene = defineComponent(() => { } }); + const replayStatus: ReplayingStatus = reactive({ + replaying: false, + playing: false, + speed: 1, + played: 0, + total: 0 + }); const leftStatus: ILeftHeroStatus = reactive({ hp: 0, atk: 0, @@ -112,26 +118,10 @@ const MainScene = defineComponent(() => { redKey: 0, floor: 'MT0', lv: '', - regen: 0, - exAtk: 0, - magicDef: 0 - }); - const replayStatus: ReplayingStatus = reactive({ - replaying: false, - playing: false, - speed: 1, - played: 0, - total: 0 + replay: replayStatus }); const rightStatus: IRightHeroStatus = reactive({ - autoSkill: false, - skillName: '', - skillDesc: '', - jumpCount: 0, - springCount: 0, - floor: 'MT0', - replayStatus, - night: 0 + exampleHard: 0 }); //#region 状态更新 @@ -140,7 +130,6 @@ const MainScene = defineComponent(() => { hideStatus.value = core.getFlag('hideStatusBar', false); const hero = core.status.hero; - const floor = core.status.floorId; leftStatus.atk = getHeroStatusOn('atk'); leftStatus.hp = getHeroStatusOn('hp'); leftStatus.def = getHeroStatusOn('def'); @@ -152,35 +141,15 @@ const MainScene = defineComponent(() => { leftStatus.redKey = core.itemCount('redKey'); leftStatus.floor = core.status.floorId; leftStatus.lv = core.getLvName(hero.lv); - leftStatus.regen = getHeroStatusOn('hpmax'); - leftStatus.exAtk = getHeroStatusOn('mana'); - leftStatus.magicDef = getHeroStatusOn('magicDef'); - rightStatus.autoSkill = HeroSkill.getAutoSkill(); - rightStatus.skillName = HeroSkill.getSkillName(); - rightStatus.skillDesc = HeroSkill.getSkillDesc(); - rightStatus.night = NightSpecial.getNight(floor); - rightStatus.floor = floor; const { pausing, speed, toReplay, totalList } = core.status.replay; replayStatus.replaying = core.isReplaying(); replayStatus.playing = !pausing; replayStatus.speed = speed; replayStatus.played = totalList.length - toReplay.length; replayStatus.total = totalList.length; - if (HeroSkill.learnedSkill(HeroSkill.Jump)) { - if (jumpIgnoreFloor.has(floor)) { - rightStatus.jumpCount = -2; - } else { - rightStatus.jumpCount = 3 - (flags[`jump_${floor}`] ?? 0); - } - } else { - rightStatus.jumpCount = -1; - } - if (core.hasFlag('spring')) { - rightStatus.springCount = 50 - (flags.springCount ?? 0); - } else { - rightStatus.springCount = -1; - } + + rightStatus.exampleHard = flags.hard; }; const updateDataFallback = () => { diff --git a/packages-user/client-modules/src/render/ui/statusBar.tsx b/packages-user/client-modules/src/render/ui/statusBar.tsx index 83657c2..779d7b8 100644 --- a/packages-user/client-modules/src/render/ui/statusBar.tsx +++ b/packages-user/client-modules/src/render/ui/statusBar.tsx @@ -1,21 +1,16 @@ import { GameUI, SetupComponentOptions } from '@motajs/system-ui'; -import { computed, defineComponent, ref, watch } from 'vue'; +import { computed, defineComponent, ref } from 'vue'; import { TextContent } from '../components'; +import { DefaultProps, ElementLocator, Font } from '@motajs/render'; import { - DefaultProps, - ElementLocator, - Sprite, - Font, - MotaOffscreenCanvas2D -} from '@motajs/render'; -import { transitionedColor } from '../use'; -import { linear } from 'mutate-animate'; -import { Scroll } from '../components'; -import { getArea, MinimapDrawer } from '@motajs/legacy-ui'; -import { MixedToolbar, ReplayingStatus } from './toolbar'; -import { HeroSkill } from '@user/data-state'; + NumpadToolbar, + PlayingToolbar, + ReplayingStatus, + ReplayingToolbar +} from './toolbar'; import { openViewMap } from './viewmap'; import { mainUIController } from './controller'; +import { MAIN_HEIGHT, STATUS_BAR_WIDTH } from '../shared'; export interface ILeftHeroStatus { hp: number; @@ -29,31 +24,12 @@ export interface ILeftHeroStatus { redKey: number; floor: FloorIds; lv: string; - /** 生命回复 */ - regen: number; - /** 额外攻击 */ - exAtk: number; - /** 魔法防御 */ - magicDef: number; + replay: ReplayingStatus; } export interface IRightHeroStatus { - /** 自动切换技能 */ - autoSkill: boolean; - /** 当前开启的技能 */ - skillName: string; - /** 技能描述 */ - skillDesc: string; - /** 跳跃剩余次数,-1 表示未开启,-2表示当前楼层不能跳 */ - jumpCount: number; - /** 治愈之泉剩余次数,-1 表示未开启 */ - springCount: number; - /** 当前楼层 */ - floor: FloorIds; - /** 录像播放状态 */ - replayStatus: ReplayingStatus; - /** 极昼永夜 */ - night: number; + /** 示例属性,以游戏难度作为示例 */ + exampleHard: number; } interface StatusBarProps extends DefaultProps { @@ -78,15 +54,20 @@ export const LeftStatusBar = defineComponent>( const s = p.status; const f = core.formatBigNumber; + const inNumpad = ref(false); + const floorName = computed(() => core.floors[s.floor]?.title ?? ''); const key = (num: number) => { return num.toString().padStart(2, '0'); }; + const onNumpad = () => { + inNumpad.value = !inNumpad.value; + }; + const font1 = Font.defaults({ size: 18 }); const font2 = Font.defaults({ size: 18, weight: 700 }); - const font3 = Font.defaults({ size: 14, weight: 700 }); const iconLoc = (n: number): ElementLocator => { return [16, 76 + 44 * n, 32, 32]; @@ -101,11 +82,6 @@ export const LeftStatusBar = defineComponent>( return [width / 2, y, void 0, void 0, 0.5, 0.5]; }; - const right = (y: number): ElementLocator => { - const width = p.loc[2] ?? 200; - return [width - 16, y, void 0, void 0, 1, 0.5]; - }; - const keyCount = 3; const keyY = 92 + 44 * 6; const keyLoc = (n: number): ElementLocator => { @@ -130,30 +106,10 @@ export const LeftStatusBar = defineComponent>( - - - {s.magicDef > 0 && ( - - )} @@ -178,214 +134,58 @@ export const LeftStatusBar = defineComponent>( font={font2} fillStyle="#f88" > - - + + {inNumpad.value ? ( + + ) : s.replay.replaying ? ( + + ) : ( + + )} ); }, statusBarProps ); -interface RightStatusBarMisc { - name: string; - value: string; - nameColor: string; - valueColor: string; -} - export const RightStatusBar = defineComponent>( p => { - const font1 = new Font('normal', 18); - const font2 = new Font('normal', 16); + // p.status 就是你在 main.tsx 中传入的属性内容,用法与左侧状态栏完全一致 - const minimap = ref(); - - const s = p.status; - const skill = computed(() => - s.autoSkill ? '已开启自动切换' : s.skillName - ); - const skillDesc = computed(() => - s.autoSkill ? '自动切换技能时,会自动选择最优技能' : s.skillDesc - ); - - const skillColor = transitionedColor('#284', 200, linear())!; - - watch( - () => s.autoSkill, - value => { - skillColor.set(value ? '#284' : '#824'); - } - ); - - const miscData = computed(() => { - const data: RightStatusBarMisc[] = []; - if (s.jumpCount !== -1) { - const text = - s.jumpCount === -2 ? '不可跳跃' : s.jumpCount.toString(); - data.push({ - name: '跳跃剩余', - nameColor: '#fff', - value: text, - valueColor: '#fff' - }); - } - if (s.springCount >= 0) { - data.push({ - name: '治愈之泉', - nameColor: '#a7ffa7', - value: s.springCount.toString(), - valueColor: '#a7ffa7' - }); - } - if (s.night !== 0) { - const text = s.night.toString(); - data.push({ - name: '极昼永夜', - nameColor: '#a3f8ff', - value: s.night > 0 ? '+' + text : text, - valueColor: s.night > 0 ? '#a7ffa7' : '#ffa7a7' - }); - } - return data; - }); - - const central = (y: number): ElementLocator => { - const width = p.loc[2] ?? 200; - return [width / 2, y, void 0, void 0, 0.5, 0.5]; - }; - - const middle = (x: number, y: number): ElementLocator => { - return [x, y, void 0, void 0, 0, 0.5]; - }; - - const changeAutoSkill = () => { - const auto = !s.autoSkill; - HeroSkill.setAutoSkill(auto); - core.status.route.push(`set:autoSkill:${auto}`); - core.updateStatusBar(); - }; - - const area = getArea(); - const minimapDrawer = new MinimapDrawer( - document.createElement('canvas') - ); - minimapDrawer.noBorder = true; - minimapDrawer.scale = 4; - minimapDrawer.showInfo = true; - let linked = false; - const drawMinimap = (canvas: MotaOffscreenCanvas2D) => { - const ctx = canvas.ctx; - ctx.scale( - 1 / core.domStyle.scale / devicePixelRatio, - 1 / core.domStyle.scale / devicePixelRatio - ); - if (!linked) { - minimapDrawer.link(canvas.canvas); - linked = true; - } - if (minimapDrawer.nowFloor !== s.floor) { - minimapDrawer.drawedThumbnail = {}; - } else { - minimapDrawer.drawToTarget(); - ctx.restore(); - return; - } - minimapDrawer.nowFloor = s.floor; - minimapDrawer.nowArea = - Object.keys(area).find(v => - area[v].includes(core.status.floorId) - ) ?? ''; - minimapDrawer.locateMap(minimapDrawer.nowFloor); - minimapDrawer.drawMap(); - }; - - watch( - () => s.floor, - () => { - minimap.value?.update(); - } - ); + const text = `这里是右侧状态栏,如果左侧状态栏不够用可以在 \\r[gold]statusBar.tsx\\r 中编写内容,如果不需要此状态栏,可以在 \\r[gold]shared.ts\\r 中关闭此状态栏。`; return () => { return ( ); diff --git a/packages-user/client-modules/src/render/ui/toolbar.tsx b/packages-user/client-modules/src/render/ui/toolbar.tsx index dd3c490..c4d3e64 100644 --- a/packages-user/client-modules/src/render/ui/toolbar.tsx +++ b/packages-user/client-modules/src/render/ui/toolbar.tsx @@ -155,6 +155,8 @@ export interface ReplayingStatus { played: number; /** 总长度 */ total: number; + /** 是否是录像模式 */ + replaying: boolean; } export interface ReplayingProps extends ToolbarProps { From 2e57b8b8062fe4a68de851bffad6c4f98284464a Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 28 Sep 2025 23:37:28 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E9=BB=98=E8=AE=A4=E7=8A=B6?= =?UTF-8?q?=E6=80=81=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 e6fe4bc..64be6a5 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 } From 850613086d47131fb80cc154ea0ae66899705512 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 28 Sep 2025 23:42:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20=E8=B0=83=E6=95=B4=E5=AD=98?= =?UTF-8?q?=E6=A1=A3=E7=95=8C=E9=9D=A2=E7=9A=84=E9=BB=98=E8=AE=A4=E9=97=B4?= =?UTF-8?q?=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages-user/client-modules/src/render/shared.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages-user/client-modules/src/render/shared.ts b/packages-user/client-modules/src/render/shared.ts index 64be6a5..744c244 100644 --- a/packages-user/client-modules/src/render/shared.ts +++ b/packages-user/client-modules/src/render/shared.ts @@ -8,9 +8,9 @@ import { Font } from '@motajs/render-style'; /** 每个格子的宽高 */ export const CELL_SIZE = 32; /** 地图格子宽度,此处仅影响画面,不影响游戏内逻辑,游戏内逻辑地图大小请在 core.js 中修改 */ -export const MAP_BLOCK_WIDTH = 15; +export const MAP_BLOCK_WIDTH = 13; /** 地图格子高度,此处仅影响画面,不影响游戏内逻辑,游戏内逻辑地图大小请在 core.js 中修改 */ -export const MAP_BLOCK_HEIGHT = 15; +export const MAP_BLOCK_HEIGHT = 13; /** 地图像素宽度 */ export const MAP_WIDTH = CELL_SIZE * MAP_BLOCK_WIDTH; /** 地图像素高度 */ @@ -75,7 +75,7 @@ export const SAVE_ITEM_DOWN = 24; /** 单个存档高度,包括存档下方的信息 */ export const SAVE_ITEM_HEIGHT = SAVE_ITEM_SIZE + SAVE_ITEM_TOP + SAVE_ITEM_DOWN; /** 存档间距 */ -export const SAVE_INTERVAL = 30; +export const SAVE_INTERVAL = 20; /** 存档下巴高度,即下方显示页码和返回按钮的高度 */ export const SAVE_DOWN_PAD = 30; /** 存档页码数,调高并不会影响性能,但是如果玩家存档太多的话会导致存档体积很大 */