From f407b5cb74f57f33e766cafe253d18f0949a6293 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Fri, 27 Sep 2024 00:13:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=A0=E9=80=81=E9=97=A8?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/game/state/move.ts | 150 +++++++++++++++++++++++++++- src/plugin/game/fallback.ts | 189 +----------------------------------- 2 files changed, 148 insertions(+), 191 deletions(-) diff --git a/src/game/state/move.ts b/src/game/state/move.ts index 26e112c..0ea5d32 100644 --- a/src/game/state/move.ts +++ b/src/game/state/move.ts @@ -11,6 +11,7 @@ import type { LayerMovingRenderable } from '@/core/render/preset/layer'; import type { LayerFloorBinder } from '@/core/render/preset/floor'; +import { BluePalace } from '../mechanism/misc'; interface MoveStepDir { type: 'dir'; @@ -369,6 +370,13 @@ interface CanMoveStatus { noPass: boolean; } +interface PortalStatus { + /** 下一步是否会步入传送门 */ + portal: boolean; + /** 传送门会传到哪 */ + data?: BluePalace.PortalTo; +} + const enum HeroMoveCode { Step, Stop, @@ -393,6 +401,9 @@ export class HeroMover extends ObjectMoverBase { /** 当前移动是否是在lockControl条件下开始的 */ private inLockControl: boolean = false; + /** 这一步的传送门信息 */ + private portalData?: BluePalace.PortalTo; + override startMove( ignoreTerrain: boolean = false, noRoute: boolean = false, @@ -439,6 +450,16 @@ export class HeroMover extends ObjectMoverBase { this.moveDir = showDir; } + // 检查传送门 + if (!this.ignoreTerrain) { + const { portal, data } = this.checkPortal(x, y, showDir); + if (portal && data) { + this.portalData = data; + await this.renderHeroSwap(data); + return HeroMoveCode.Portal; + } + } + const dir = this.moveDir; if (!this.ignoreTerrain) { const { noPass, canMove } = this.checkCanMove(x, y, showDir); @@ -482,9 +503,17 @@ export class HeroMover extends ObjectMoverBase { } // 本次移动正常完成 - if (code === HeroMoveCode.Step) { - core.setHeroLoc('x', nx, true); - core.setHeroLoc('y', ny, true); + if (code === HeroMoveCode.Step || code === HeroMoveCode.Portal) { + if (code === HeroMoveCode.Portal) { + const data = this.portalData; + if (!data) return; + core.setHeroLoc('x', data.x); + core.setHeroLoc('y', data.y); + core.setHeroLoc('direction', data.dir); + } else { + core.setHeroLoc('x', nx, true); + core.setHeroLoc('y', ny, true); + } const direction = core.getHeroLoc('direction'); core.control._moveAction_popAutomaticRoute(); @@ -555,6 +584,121 @@ export class HeroMover extends ObjectMoverBase { const ny = y + dy; return { x: nx, y: ny }; } + + /** + * 检查前方一格是否会步入传送门 + * @param x 横坐标 + * @param y 纵坐标 + * @param dir 移动方向 + */ + private checkPortal(x: number, y: number, dir: Dir): PortalStatus { + const map = BluePalace.portalMap.get(core.status.floorId); + if (!map) { + return { portal: false }; + } + const width = core.status.thisMap.width; + const index = x + y * width; + const data = map?.get(index); + if (!data) { + return { portal: false }; + } + const to = data[dir]; + if (to) { + return { portal: true, data: to }; + } + return { portal: false }; + } + + private renderHeroSwap(data: BluePalace.PortalTo) { + const adapter = HeroMover.adapter; + if (!adapter) return; + const list = adapter.items; + const { x: tx, y: ty, dir: toDir } = data; + const { x, y, direction } = core.status.hero.loc; + const { x: dx, y: dy } = core.utils.scan[direction]; + const { x: tdx } = core.utils.scan[toDir]; + + const promises = [...list].map(v => { + if (!v.renderable) return; + const renderable = { ...v.renderable }; + renderable.render = v.getRenderFromDir(toDir); + renderable.zIndex = ty; + const heroDir = v.moveDir; + + const width = v.renderable.render[0][2]; + const height = v.renderable.render[0][3]; + const cell = v.layer.cellSize; + const restHeight = height - cell; + if (!width || !height) return; + + const originFrom = structuredClone(v.renderable.render); + const originTo = structuredClone(renderable.render); + v.layer.moving.add(renderable); + v.layer.requestUpdateMoving(); + + const start = Date.now(); + return new Promise(res => { + const tick = () => { + const now = Date.now(); + const progress = (now - start) / this.moveSpeed; + const clipWidth = cell * progress; + const clipHeight = cell * progress; + const beforeWidth = width - clipWidth; + const beforeHeight = height - clipHeight; + + v.renderable!.x = x; + v.renderable!.y = y; + if (heroDir === 'left' || heroDir === 'right') { + v.renderable!.x = x + (clipWidth / 2 / cell) * dx; + v.renderable!.render.forEach((v, i) => { + v[2] = beforeWidth; + if (heroDir === 'left') { + v[0] = originFrom[i][0] + clipWidth; + } + }); + } else { + v.renderable!.render.forEach((v, i) => { + v[3] = beforeHeight; + if (heroDir === 'up') { + v[1] = + originFrom[i][1] + clipHeight + restHeight; + } + }); + } + + renderable.x = tx; + renderable.y = ty; + if (toDir === 'left' || toDir === 'right') { + renderable.x = tx + (clipWidth / 2 / cell - 0.5) * tdx; + renderable.render.forEach((v, i) => { + v[2] = clipWidth; + if (toDir === 'right') { + v[0] = originTo[i][0] + beforeWidth; + } + }); + } else { + if (toDir === 'down') renderable.y = ty - 1 + progress; + renderable.render.forEach((v, i) => { + v[3] = clipHeight + restHeight; + if (toDir === 'down') { + v[1] = originTo[i][1] + clipHeight + restHeight; + v[3] = clipHeight; + } + }); + } + }; + v.layer.delegateTicker(tick, this.moveSpeed, () => { + v.renderable!.render = originFrom; + v.setAnimateDir(data.dir); + v.layer.moving.delete(renderable); + v.layer.requestUpdateMoving(); + res(); + }); + }); + }); + + return Promise.all(promises); + } } interface HeroMoveCollection { diff --git a/src/plugin/game/fallback.ts b/src/plugin/game/fallback.ts index e18df01..dc0f5ff 100644 --- a/src/plugin/game/fallback.ts +++ b/src/plugin/game/fallback.ts @@ -5,9 +5,7 @@ import type { LayerFloorBinder } from '@/core/render/preset/floor'; import type { HeroRenderer } from '@/core/render/preset/hero'; -import type { Layer, LayerMovingRenderable } from '@/core/render/preset/layer'; -import { BluePalace } from '@/game/mechanism/misc'; -import { backDir } from './utils'; +import type { Layer } from '@/core/render/preset/layer'; import type { TimingFn } from 'mutate-animate'; import { BlockMover, heroMoveCollection, MoveStep } from '@/game/state/move'; import type { FloorViewport } from '@/core/render/preset/viewport'; @@ -44,159 +42,8 @@ export function init() { adapters['viewport'] = viewport; } - /** 传送门信息,下一步传送到哪 */ - let portalData: BluePalace.PortalTo | undefined; - /** 下一步是否步入传送门 */ - let portal: boolean = false; - const { mover: heroMover } = heroMoveCollection; - function onMoveEnd( - noPass: boolean, - noRoute: boolean = false, - callback?: () => void - ) { - // if (portal && portalData) { - // const before = moveDir; - // const { x, y, dir } = portalData; - // core.setHeroLoc('x', x); - // core.setHeroLoc('y', y); - // core.setHeroLoc('direction', dir); - // portal = false; - // moveDir = before; - // } - - var direction = core.getHeroLoc('direction'); - core.control._moveAction_popAutomaticRoute(); - if (!noRoute) core.status.route.push(direction); - - core.moveOneStep(); - core.checkRouteFolding(); - callback?.(); - } - - // ----- 移动 - 传送门 - function checkPortal() { - const map = BluePalace.portalMap.get(core.status.floorId); - if (!map) { - portal = false; - portalData = void 0; - return; - } - const width = core.status.thisMap.width; - const { x, y, direction } = core.status.hero.loc; - const index = x + y * width; - const data = map?.get(index); - if (!data) { - portal = false; - portalData = void 0; - return; - } - const to = data[direction]; - if (to) { - portal = true; - portalData = to; - } - } - - const end: Record = { - left: [-1, 0], - right: [1, 0], - down: [0, 1], - up: [0, -1] - }; - - /** - * 对勇士进行切割渲染,分成两个renderable进行渲染 - */ - function renderHeroSwap() { - if (!portal || !portalData) return; - const list = adapters['hero-adapter']?.items; - if (!list) return; - const { x: tx, y: ty, dir: toDir } = portalData; - const { x, y, direction } = core.status.hero.loc; - const [dx, dy] = end[direction]; - const [tdx] = end[toDir]; - const checkX = x + dx; - const checkY = y + dy; - - list.forEach(v => { - if (!v.renderable) return; - const renderable = { ...v.renderable }; - renderable.render = v.getRenderFromDir(toDir); - renderable.zIndex = ty; - const heroDir = v.moveDir; - - const width = v.renderable.render[0][2]; - const height = v.renderable.render[0][3]; - const cell = v.layer.cellSize; - const restHeight = height - cell; - if (!width || !height) return; - - const originFrom = structuredClone(v.renderable.render); - const originTo = structuredClone(renderable.render); - v.layer.moving.add(renderable); - v.layer.requestUpdateMoving(); - v.on('moveTick', function func() { - const progress = - heroDir === 'left' || heroDir === 'right' - ? 1 - Math.abs(checkX - v.renderable!.x) - : 1 - Math.abs(checkY - v.renderable!.y); - if (progress >= 1 || !portal) { - v.renderable!.render = originFrom; - v.off('moveTick', func); - v.layer.moving.delete(renderable); - v.layer.requestUpdateMoving(); - return; - } - const clipWidth = cell * progress; - const clipHeight = cell * progress; - const beforeWidth = width - clipWidth; - const beforeHeight = height - clipHeight; - - v.renderable!.x = x; - v.renderable!.y = y; - if (heroDir === 'left' || heroDir === 'right') { - v.renderable!.x = x + (clipWidth / 2 / cell) * dx; - v.renderable!.render.forEach((v, i) => { - v[2] = beforeWidth; - if (heroDir === 'left') { - v[0] = originFrom[i][0] + clipWidth; - } - }); - } else { - v.renderable!.render.forEach((v, i) => { - v[3] = beforeHeight; - if (heroDir === 'up') { - v[1] = originFrom[i][1] + clipHeight + restHeight; - } - }); - } - - renderable.x = tx; - renderable.y = ty; - if (toDir === 'left' || toDir === 'right') { - renderable.x = tx + (clipWidth / 2 / cell - 0.5) * tdx; - renderable.render.forEach((v, i) => { - v[2] = clipWidth; - if (toDir === 'right') { - v[0] = originTo[i][0] + beforeWidth; - } - }); - } else { - if (toDir === 'down') renderable.y = ty - 1 + progress; - renderable.render.forEach((v, i) => { - v[3] = clipHeight + restHeight; - if (toDir === 'down') { - v[1] = originTo[i][1] + clipHeight + restHeight; - v[3] = clipHeight; - } - }); - } - }); - }); - } - // ----- 工具函数 /** @@ -218,40 +65,6 @@ export function init() { return moveSteps; } - /** - * 移动一个LayerMovingRenderable - */ - function moveRenderable( - item: Layer, - data: LayerMovingRenderable, - time: number, - x: number, - y: number - ) { - const fx = data.x; - const fy = data.y; - const dx = x - fx; - const dy = y - fy; - const start = Date.now(); - return new Promise(res => { - item.delegateTicker( - () => { - const now = Date.now() - start; - const progress = now / time; - data.x = fx + dx * progress; - data.y = fy + dy * progress; - item.update(item); - }, - time, - () => { - data.x = x; - data.y = y; - res(); - } - ); - }); - } - /** * 生成跳跃函数 */