diff --git a/src/core/render/preset/hero.ts b/src/core/render/preset/hero.ts index e66dc5d..6a16ae2 100644 --- a/src/core/render/preset/hero.ts +++ b/src/core/render/preset/hero.ts @@ -4,8 +4,9 @@ import { RenderAdapter } from '../adapter'; import { logger } from '@/core/common/logger'; import EventEmitter from 'eventemitter3'; import { texture } from '../cache'; +import { TimingFn } from 'mutate-animate'; -type HeroMovingStatus = 'stop' | 'moving'; +type HeroMovingStatus = 'stop' | 'moving' | 'moving-as'; interface HeroRenderEvent { stepEnd: []; @@ -222,6 +223,50 @@ export class HeroRenderer this.layer.update(this.layer); } + /** + * 按照指定函数移动勇士 + * @param x 目标横坐标 + * @param y 目标纵坐标 + * @param time 移动时间 + * @param fn 移动函数,传入一个完成度(范围0-1),返回一个三元素数组,表示横纵格子坐标,可以是小数。 + * 第三个元素表示图块纵深,一般图块的纵深就是其纵坐标,当地图上有大怪物时,此举可以辅助渲染, + * 否则可能会导致移动过程中与大怪物的层级关系不正确,比如全在大怪物身后。注意不建议频繁改动这个值, + * 因为此举会导致层级的重新排序,降低渲染性能。 + */ + moveAs(x: number, y: number, time: number, fn: TimingFn<3>) { + if (this.status !== 'stop') return; + if (!this.renderable) return; + this.status = 'moving-as'; + let nowZIndex = fn(0)[2]; + let startTime = Date.now(); + this.layer.delegateTicker( + () => { + if (!this.renderable) return; + const now = Date.now(); + const progress = (now - startTime) / time; + const [nx, ny, nz] = fn(progress); + this.renderable.x = nx; + this.renderable.y = ny; + this.renderable.zIndex = nz; + if (nz !== nowZIndex) { + this.layer.movingRenderable.sort( + (a, b) => a.zIndex - b.zIndex + ); + } + this.layer.update(this.layer); + }, + time, + () => { + this.status = 'stop'; + if (!this.renderable) return; + this.renderable.animate = 0; + this.renderable.x = x; + this.renderable.y = y; + this.layer.update(this.layer); + } + ); + } + /** * 渲染勇士 */ diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index 603d620..a30936b 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -602,7 +602,6 @@ export interface ILayerRenderExtends { interface LayerCacheItem { // todo: 删掉这个属性 - floorId?: FloorIds; canvas: HTMLCanvasElement; } @@ -674,8 +673,6 @@ export class Layer extends Container { /** 最终渲染至的Sprite */ main: Sprite = new Sprite(); - /** 渲染的楼层 */ - floorId?: FloorIds; /** 渲染的层 */ layer?: FloorLayer; // todo: renderable分块存储,优化循环绘制性能 @@ -1256,7 +1253,7 @@ export class Layer extends Container { const index = v * 4 + frame - 1; const cache = this.block.cache.get(index); - if (cache && cache.floorId === this.floorId) { + if (cache) { ctx.drawImage( cache.canvas, sx * cell, @@ -1285,12 +1282,7 @@ export class Layer extends Container { const data = texture.getRenderable(num); if (!data || data.bigImage) continue; const f = (frame - 1) % data.frame; - const i = - data.animate === -1 - ? frame === 4 && data.frame === 3 - ? 1 - : f - : data.animate; + const i = data.animate === -1 ? f : data.animate; const [isx, isy, w, h] = data.render[i]; const px = (nx - sx) * cell; const py = (ny - sy) * cell; @@ -1312,8 +1304,7 @@ export class Layer extends Container { blockSize * cell ); this.block.cache.set(index, { - canvas: temp.canvas, - floorId: this.floorId + canvas: temp.canvas }); }); @@ -1347,12 +1338,7 @@ export class Layer extends Container { this.movingRenderable.forEach(v => { const { x, y, image, frame: blockFrame, render, animate } = v; const ff = frame % 4; - const i = - animate === -1 - ? frame === 4 && blockFrame === 3 - ? 1 - : ff - : animate; + const i = animate === -1 ? ff : animate; const [sx, sy, w, h] = render[i]; const px = x * cell - w / 2 + halfCell; const py = y * cell - h + cell;