diff --git a/packages-user/client-modules/src/render/ui/main.tsx b/packages-user/client-modules/src/render/ui/main.tsx index bfc37c2..2446fa0 100644 --- a/packages-user/client-modules/src/render/ui/main.tsx +++ b/packages-user/client-modules/src/render/ui/main.tsx @@ -1,5 +1,12 @@ import { LayerShadowExtends } from '../legacy/shadow'; -import { Props, Font, IActionEvent } from '@motajs/render'; +import { + Props, + Font, + IActionEvent, + MotaOffscreenCanvas2D, + Sprite, + onTick +} from '@motajs/render'; import { WeatherController } from '../../weather'; import { defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue'; import { Textbox, Tip } from '../components'; @@ -38,8 +45,10 @@ import { LayerDoorAnimate, LayerGroup } from '../elements'; +import { isNil } from 'lodash-es'; const MainScene = defineComponent(() => { + //#region 基本定义 const layerGroupExtends: ILayerGroupRenderExtends[] = [ new FloorDamageExtends(), new FloorItemDetail(), @@ -54,10 +63,6 @@ const MainScene = defineComponent(() => { new LayerDoorAnimate(), new LayerShadowExtends() ]; - const mapDrawProps: Props<'container'> = { - width: core._PX_, - height: core._PY_ - }; const mainTextboxProps: Props = { text: '', hidden: true, @@ -78,6 +83,11 @@ const MainScene = defineComponent(() => { const locked = ref(false); const weather = new WeatherController('main'); + const loaded = ref(true); + onLoaded(() => { + loaded.value = true; + }); + onMounted(() => { weather.bind(map.value); }); @@ -116,6 +126,7 @@ const MainScene = defineComponent(() => { night: 0 }); + //#region 状态更新 const updateStatus = () => { if (!core.status || !core.status.hero || !core.status.floorId) return; hideStatus.value = core.getFlag('hideStatusBar', false); @@ -169,10 +180,62 @@ const MainScene = defineComponent(() => { locked.value = core.status.lockControl; }; + // 监听状态栏更新事件 + hook.on('statusBarUpdate', updateStatus); + hook.on('statusBarUpdate', updateDataFallback); + + onUnmounted(() => { + hook.off('statusBarUpdate', updateStatus); + hook.off('statusBarUpdate', updateDataFallback); + }); + + //#region sprite 渲染 + + let lastLength = 0; + onTick(() => { + const len = core.status.stepPostfix?.length ?? 0; + if (len !== lastLength) { + mapMiscSprite.value?.update(); + lastLength = len; + } + }); + + const mapMiscSprite = ref(); + + const renderMapMisc = (canvas: MotaOffscreenCanvas2D) => { + const step = core.status.stepPostfix; + if (!step) return; + const ctx = canvas.ctx; + ctx.save(); + ctx.fillStyle = '#fff'; + step.forEach(({ x, y, direction }) => { + ctx.fillRect(x * 32 + 12, y * 32 + 12, 8, 8); + if (!isNil(direction)) { + switch (direction) { + case 'down': + ctx.fillRect(x * 32 + 12, y * 32 + 20, 8, 12); + break; + case 'left': + ctx.fillRect(x * 32, y * 32 + 12, 12, 8); + break; + case 'right': + ctx.fillRect(x * 32 + 20, y * 32 + 12, 12, 8); + break; + case 'up': + ctx.fillRect(x * 32 + 12, y * 32, 8, 12); + break; + } + } + }); + ctx.restore(); + }; + + //#region 交互监听 + /** * 对于 registerAction 的 fallback */ - const clickData = (ev: IActionEvent) => { + const clickMap = (ev: IActionEvent) => { const bx = Math.floor(ev.offsetX / 32); const by = Math.floor(ev.offsetY / 32); core.doRegisteredAction('onup', bx, by, ev.offsetX, ev.offsetY); @@ -181,7 +244,7 @@ const MainScene = defineComponent(() => { /** * 对于 registerAction 的 fallback */ - const downData = (ev: IActionEvent) => { + const downMap = (ev: IActionEvent) => { const bx = Math.floor(ev.offsetX / 32); const by = Math.floor(ev.offsetY / 32); core.doRegisteredAction('ondown', bx, by, ev.offsetX, ev.offsetY); @@ -190,25 +253,12 @@ const MainScene = defineComponent(() => { /** * 对于 registerAction 的 fallback */ - const moveData = (ev: IActionEvent) => { + const moveMap = (ev: IActionEvent) => { const bx = Math.floor(ev.offsetX / 32); const by = Math.floor(ev.offsetY / 32); core.doRegisteredAction('onmove', bx, by, ev.offsetX, ev.offsetY); }; - const loaded = ref(true); - onLoaded(() => { - loaded.value = true; - }); - - hook.on('statusBarUpdate', updateStatus); - hook.on('statusBarUpdate', updateDataFallback); - - onUnmounted(() => { - hook.off('statusBarUpdate', updateStatus); - hook.off('statusBarUpdate', updateDataFallback); - }); - return () => ( {loaded.value && ( @@ -219,7 +269,14 @@ const MainScene = defineComponent(() => { > )} - + @@ -238,13 +295,11 @@ const MainScene = defineComponent(() => { corner={16} /> diff --git a/public/libs/actions.js b/public/libs/actions.js index ca32512..12615d9 100644 --- a/public/libs/actions.js +++ b/public/libs/actions.js @@ -576,7 +576,6 @@ actions.prototype._sys_ondown_lockControl = function (x, y, px, py) { actions.prototype._sys_ondown = function (x, y, px, py) { if (core.status.lockControl) return false; core.status.downTime = new Date(); - core.deleteCanvas('route'); var pos = { x: Math.floor((px + core.bigmap.offsetX) / 32), y: Math.floor((py + core.bigmap.offsetY) / 32) @@ -591,14 +590,6 @@ actions.prototype._sys_ondown = function (x, y, px, py) { core.status.stepPostfix = []; core.status.stepPostfix.push(pos); - core.fillRect( - 'ui', - pos.x * 32 + 12 - core.bigmap.offsetX, - pos.y * 32 + 12 - core.bigmap.offsetY, - 8, - 8, - '#bfbfbf' - ); clearTimeout(core.timeout.onDownTimeout); core.timeout.onDownTimeout = null; @@ -688,14 +679,6 @@ actions.prototype._sys_onmove = function (x, y, px, py) { pos.x += pos0.x; pos.y += pos0.y; core.status.stepPostfix.push(pos); - core.fillRect( - 'ui', - pos.x * 32 + 12 - core.bigmap.offsetX, - pos.y * 32 + 12 - core.bigmap.offsetY, - 8, - 8, - '#bfbfbf' - ); } } return true; @@ -736,9 +719,6 @@ actions.prototype._sys_onup = function (x, y, px, py) { var posx = core.status.stepPostfix[0].x; var posy = core.status.stepPostfix[0].y; core.status.stepPostfix = []; - if (!core.status.lockControl) { - core.clearMap('ui'); - } // 长按 if ( diff --git a/src/types/declaration/status.d.ts b/src/types/declaration/status.d.ts index 7a854f0..6989cf8 100644 --- a/src/types/declaration/status.d.ts +++ b/src/types/declaration/status.d.ts @@ -765,6 +765,8 @@ interface GameStatus extends InitGameStatus { * 当前勇士状态信息。例如core.status.hero.atk就是当前勇士的攻击力数值 */ hero: HeroStatus; + + stepPostfix?: DiredLoc[]; } interface Follower { diff --git a/vite.config.ts b/vite.config.ts index c1c1bd8..3c82cd4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,11 @@ import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import components from 'unplugin-vue-components/vite'; -import vuejsx from '@vitejs/plugin-vue-jsx' +import vuejsx from '@vitejs/plugin-vue-jsx'; import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'; import path from 'path'; import postcssPresetEnv from 'postcss-preset-env'; -import * as glob from 'glob' +import * as glob from 'glob'; const FSHOST = 'http://127.0.0.1:3000/'; @@ -13,7 +13,7 @@ const custom = [ 'container', 'image', 'sprite', 'shader', 'text', 'comment', 'custom', 'layer', 'layer-group', 'animate', 'damage', 'graphics', 'icon', 'winskin', 'container-custom' -] +]; const aliases = glob.sync('packages/*/src').map((srcPath) => { const packageName = path.basename(path.dirname(srcPath));