From 0fed6b09c35e8f8b2e57ff2c20ee9f46408cfac1 Mon Sep 17 00:00:00 2001 From: qdzwxe Date: Tue, 26 Sep 2023 18:32:10 +0800 Subject: [PATCH] feat: fading path of direct move --- public/libs/control.js | 12 +++++- public/libs/maps.js | 75 +++++++++++++++++++++++++------------ public/project/functions.js | 2 +- src/core/main/game.ts | 6 +-- src/core/main/setting.ts | 58 ++++++++++------------------ 5 files changed, 86 insertions(+), 67 deletions(-) diff --git a/public/libs/control.js b/public/libs/control.js index 02cca5c..c0d724e 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -976,7 +976,11 @@ control.prototype.tryMoveDirectly = function (destX, destY) { [destX, destY + 1, 'up'], [destX + 1, destY, 'left'] ]; - var canMoveDirectlyArray = core.canMoveDirectlyArray(dirs, canMoveArray); + const { ans: canMoveDirectlyArray, route } = core.canMoveDirectlyArray( + dirs, + canMoveArray + ); + let { x, y } = core.getHeroLoc(); for (let i = 0; i < dirs.length; ++i) { var d = dirs[i]; @@ -995,6 +999,12 @@ control.prototype.tryMoveDirectly = function (destX, destY) { if (dir) { core.moveHero(dir, function () {}); } + mota.game.hook.emit( + 'beforeMoveDirectly', + x, + y, + core.routeToMoveSteps(x, y, dx, dy, route) + ); return true; } } diff --git a/public/libs/maps.js b/public/libs/maps.js index 493f872..cf055a8 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -880,7 +880,7 @@ maps.prototype._canMoveHero_checkCannotInOut = function ( ////// 能否瞬间移动 ////// maps.prototype.canMoveDirectly = function (destX, destY) { - return this.canMoveDirectlyArray([[destX, destY]])[0]; + return this.canMoveDirectlyArray([[destX, destY]]).ans[0]; }; maps.prototype.canMoveDirectlyArray = function (locs, canMoveArray) { @@ -954,54 +954,71 @@ maps.prototype._canMoveDirectly_bfs = function ( locs, number, ans, - canMoveArray + canMoveArray = this.generateMovableArray() ) { - canMoveArray = canMoveArray || this.generateMovableArray(); - var blocksObj = this.getMapBlocksObj(); - // 滑冰 - var bgMap = this.getBgMapArray(); + const blocksObj = this.getMapBlocksObj(), + // 滑冰 + bgMap = this.getBgMapArray(); + + let visited = {}, + route = {}; + let queue = new PriorityQueue({ + comparator: function (a, b) { + return a.depth - b.depth; + } + }); - var visited = [], - queue = []; visited[sx + ',' + sy] = 0; - queue.push(sx + ',' + sy); + route[sx + ',' + sy] = ''; + queue.queue({ depth: 0, x: sx, y: sy }); - while (queue.length > 0) { - var now = queue.shift().split(','), - x = parseInt(now[0]), - y = parseInt(now[1]); - for (var direction in core.utils.scan) { + while (queue.length != 0) { + const curr = queue.dequeue(); + const { depth, x, y } = curr; + const now = x + ',' + y; + for (const direction in core.utils.scan) { if (!core.inArray(canMoveArray[x][y], direction)) continue; - var nx = x + core.utils.scan[direction].x, - ny = y + core.utils.scan[direction].y, - nindex = nx + ',' + ny; + const nx = x + core.utils.scan[direction].x; + const ny = y + core.utils.scan[direction].y; + const nindex = nx + ',' + ny; if (visited[nindex]) continue; + if ( + nx < 0 || + nx >= core.bigmap.width || + ny < 0 || + ny >= core.bigmap.height || + route[nx + ',' + ny] != null + ) + continue; if (core.onSki(bgMap[ny][nx])) continue; if (!this._canMoveDirectly_checkNextPoint(blocksObj, nx, ny)) continue; + // 不可通行 + if (core.noPass(nx, ny)) continue; + route[nx + ',' + ny] = direction; visited[nindex] = visited[now] + 1; // if (nx == ex && ny == ey) return visited[nindex]; - for (var i in ans) { + for (const i in ans) { if (locs[i][0] == nx && locs[i][1] == ny && ans[i] == null) { // 不可以绿点为终点 - var block = blocksObj[nx + ',' + ny]; + const block = blocksObj[nindex]; if (block && !block.disable && block.event.trigger) { ans[i] = -1; } else { ans[i] = visited[nindex]; } number--; - if (number == 0) return ans; + if (number == 0) return { ans, route }; } } - queue.push(nindex); + queue.queue({ depth: depth + 1, x: nx, y: ny }); } } for (var i in ans) { if (ans[i] == null) ans[i] = -1; } - return ans; + return { ans, route }; }; maps.prototype._canMoveDirectly_checkNextPoint = function (blocksObj, x, y) { @@ -1040,7 +1057,17 @@ maps.prototype.automaticRoute = function (destX, destY) { // BFS找寻最短路径 var route = this._automaticRoute_bfs(startX, startY, destX, destY); if (route[destX + ',' + destY] == null) return []; - // 路径数组转换 + return this.routeToMoveSteps(startX, startY, destX, destY, route); +}; + +// 路径数组转换 +maps.prototype.routeToMoveSteps = function ( + startX, + startY, + destX, + destY, + route +) { var ans = [], nowX = destX, nowY = destY; @@ -1083,7 +1110,7 @@ maps.prototype._automaticRoute_bfs = function (startX, startY, destX, destY) { route[nx + ',' + ny] != null ) continue; - // 重点 + // 终点 if (nx == destX && ny == destY) { route[nx + ',' + ny] = direction; break; diff --git a/public/project/functions.js b/public/project/functions.js index 31fd771..a369523 100644 --- a/public/project/functions.js +++ b/public/project/functions.js @@ -177,7 +177,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { else core.setWeather(); checkLoopMap(); - + core.deleteCanvas('route2'); // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 }, afterChangeFloor: function (floorId) { diff --git a/src/core/main/game.ts b/src/core/main/game.ts index 6330bda..d85c64c 100644 --- a/src/core/main/game.ts +++ b/src/core/main/game.ts @@ -2,11 +2,11 @@ import { EmitableEvent, EventEmitter } from '../common/eventEmitter'; export interface GameEvent extends EmitableEvent { reset: () => void; - moveDirectly: ( + beforeMoveDirectly: ( x: number, y: number, - moveSteps: Array<{ direction: string; step: number }>, - ctx: CanvasRenderingContext2D + moveSteps: { direction: Dir; step: number }[], + ctxName: string ) => void; } diff --git a/src/core/main/setting.ts b/src/core/main/setting.ts index 61bbd26..1b19cb4 100644 --- a/src/core/main/setting.ts +++ b/src/core/main/setting.ts @@ -430,55 +430,37 @@ hook.on('reset', () => { }); }); -hook.on('moveDirectly', (x, y, moveSteps, ctx) => { - // 计算绘制区域的宽高,并尽可能小的创建route层 - // var sx = core.bigmap.width * 32, - // sy = core.bigmap.height * 32, - // dx = 0, - // dy = 0; - // moveStep.forEach(function (t) { - // sx = Math.min(sx, t.x * 32); - // dx = Math.max(dx, t.x * 32); - // sy = Math.min(sy, t.y * 32); - // dy = Math.max(dy, t.y * 32); - // }); - // core.status.automaticRoute.offsetX = sx; - // core.status.automaticRoute.offsetY = sy; - // var ctx = core.createCanvas( - // 'route', - // sx - core.bigmap.offsetX, - // sy - core.bigmap.offsetY, - // dx - sx + 32, - // dy - sy + 32, - // 95 - // ); +hook.on('beforeMoveDirectly', (x, y, moveSteps, ctxName = 'route2') => { + core.deleteCanvas(ctxName); + const ctx = core.createCanvas(ctxName, 0, 0, 480, 480, 15); ctx.clearRect(0, 0, 480, 480); ctx.fillStyle = '#bfbfbf'; ctx.strokeStyle = '#bfbfbf'; ctx.lineWidth = 4; - const scan: { [key: string]: { [key: string]: number } } = { - up: { x: 0, y: -1 }, - left: { x: -1, y: 0 }, - down: { x: 0, y: 1 }, - right: { x: 1, y: 0 } - }; for (let m = 0; m < moveSteps.length; m++) { - if (m == moveSteps.length - 1) { + if (m === 0) ctx.fillRect(x * 32 + 10, y * 32 + 10, 12, 12); + const currDir = moveSteps[m].direction; + x += core.utils.scan[currDir].x; + y += core.utils.scan[currDir].y; + if (m === moveSteps.length - 1) ctx.fillRect(x * 32 + 10, y * 32 + 10, 12, 12); - } else { - ctx.beginPath(); + else { + const nextDir = moveSteps[m + 1].direction; const cx = x * 32 + 16, cy = y * 32 + 16; - const currDir = moveSteps[m].direction, - nextDir = moveSteps[m + 1].direction; - ctx.moveTo(cx - scan[currDir].x * 11, cy - scan[currDir].y * 11); + ctx.beginPath(); + ctx.moveTo( + cx - core.utils.scan[currDir].x * 11, + cy - core.utils.scan[currDir].y * 11 + ); ctx.lineTo(cx, cy); - ctx.lineTo(cx + scan[nextDir].x * 11, cy + scan[nextDir].y * 11); + ctx.lineTo( + cx + core.utils.scan[nextDir].x * 11, + cy + core.utils.scan[nextDir].y * 11 + ); ctx.stroke(); - x += scan[currDir].x; - y += scan[currDir].y; } } - ctx.canvas.style.transition = 'all 1s linear'; + ctx.canvas.style.transition = 'all 0.6s ease-in'; nextFrame(() => (ctx.canvas.style.opacity = '0')); });