mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 12:49:25 +08:00
feat: 平滑视角
This commit is contained in:
parent
ef50b985cb
commit
cd9c95d24d
@ -23,8 +23,12 @@ export class Container<E extends EContainerEvent = EContainerEvent>
|
||||
* @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动
|
||||
* @param cache 是否启用缓存机制
|
||||
*/
|
||||
constructor(type: RenderItemPosition = 'static', cache: boolean = true) {
|
||||
super(type, cache);
|
||||
constructor(
|
||||
type: RenderItemPosition = 'static',
|
||||
cache: boolean = true,
|
||||
fall: boolean = false
|
||||
) {
|
||||
super(type, cache, fall);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import { LayerGroupFilter } from '@/plugin/fx/gameCanvas';
|
||||
import { LayerGroupAnimate } from './preset/animate';
|
||||
import { LayerGroupPortal } from '@/plugin/fx/portal';
|
||||
import { LayerGroupHalo } from '@/plugin/fx/halo';
|
||||
import { FloorViewport } from './preset/viewport';
|
||||
|
||||
let main: MotaRenderer;
|
||||
|
||||
@ -37,6 +38,7 @@ Mota.require('var', 'loading').once('loaded', () => {
|
||||
const animate = new LayerGroupAnimate();
|
||||
const portal = new LayerGroupPortal();
|
||||
const halo = new LayerGroupHalo();
|
||||
const viewport = new FloorViewport();
|
||||
layer.extends(damage);
|
||||
layer.extends(detail);
|
||||
layer.extends(filter);
|
||||
@ -46,6 +48,7 @@ Mota.require('var', 'loading').once('loaded', () => {
|
||||
layer.getLayer('event')?.extends(door);
|
||||
layer.getLayer('event')?.extends(shadow);
|
||||
layer.extends(animate);
|
||||
layer.extends(viewport);
|
||||
|
||||
render.appendChild(layer);
|
||||
// console.log(render);
|
||||
|
@ -119,6 +119,7 @@ export interface ERenderItemEvent {
|
||||
|
||||
interface TickerDelegation {
|
||||
fn: TickerFn;
|
||||
timeout?: number;
|
||||
endFn?: () => void;
|
||||
}
|
||||
|
||||
@ -179,11 +180,18 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
protected cacheDirty: boolean = true;
|
||||
/** 是否启用缓存机制 */
|
||||
readonly enableCache: boolean = true;
|
||||
/** 是否启用transform下穿机制 */
|
||||
readonly transformFallThrough: boolean = false;
|
||||
|
||||
constructor(type: RenderItemPosition, enableCache: boolean = true) {
|
||||
constructor(
|
||||
type: RenderItemPosition,
|
||||
enableCache: boolean = true,
|
||||
transformFallThrough: boolean = false
|
||||
) {
|
||||
super();
|
||||
|
||||
this.enableCache = enableCache;
|
||||
this.transformFallThrough = transformFallThrough;
|
||||
this.type = type;
|
||||
|
||||
this.cache.withGameScale(true);
|
||||
@ -222,7 +230,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
if (this.hidden) return;
|
||||
this.emit('beforeRender', transform);
|
||||
this.needUpdate = false;
|
||||
const tran = this.transform;
|
||||
const tran = this.transformFallThrough ? transform : this.transform;
|
||||
|
||||
const ax = -this.anchorX * this.width;
|
||||
const ay = -this.anchorY * this.height;
|
||||
@ -320,7 +328,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
RenderItem.tickerMap.set(id, delegation);
|
||||
RenderItem.ticker.add(fn);
|
||||
if (typeof time === 'number' && time < 2147438647 && time > 0) {
|
||||
setTimeout(() => {
|
||||
delegation.timeout = window.setTimeout(() => {
|
||||
RenderItem.ticker.remove(fn);
|
||||
end?.();
|
||||
}, time);
|
||||
@ -332,6 +340,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
const delegation = RenderItem.tickerMap.get(id);
|
||||
if (!delegation) return false;
|
||||
RenderItem.ticker.remove(delegation.fn);
|
||||
window.clearTimeout(delegation.timeout);
|
||||
if (callEnd) delegation.endFn?.();
|
||||
return true;
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ export class Damage extends Sprite<EDamageEvent> {
|
||||
private needUpdateBlocks: Set<number> = new Set();
|
||||
|
||||
constructor() {
|
||||
super('absolute', false);
|
||||
super('absolute', false, true);
|
||||
|
||||
this.block = new BlockCacher(0, 0, core._WIDTH_, 1);
|
||||
this.type = 'absolute';
|
||||
@ -175,11 +175,11 @@ export class Damage extends Sprite<EDamageEvent> {
|
||||
this.damageMap.setAntiAliasing(true);
|
||||
this.damageMap.size(core._PX_, core._PY_);
|
||||
|
||||
this.setRenderFn((canvas, camera) => {
|
||||
this.setRenderFn((canvas, transform) => {
|
||||
const { ctx } = canvas;
|
||||
const { width, height } = canvas;
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
this.renderDamage(camera);
|
||||
this.renderDamage(transform);
|
||||
ctx.drawImage(this.damageMap.canvas, 0, 0, width, height);
|
||||
});
|
||||
}
|
||||
|
@ -107,11 +107,14 @@ export class LayerGroup extends Container implements IAnimateFrame {
|
||||
/** 地图显示层 */
|
||||
layers: Map<FloorLayer, Layer> = new Map();
|
||||
|
||||
/** 这个地图组的摄像机 */
|
||||
camera: Transform = new Transform();
|
||||
|
||||
private needRender?: NeedRenderData;
|
||||
private extend: Map<string, ILayerGroupRenderExtends> = new Map();
|
||||
|
||||
constructor() {
|
||||
super('static');
|
||||
super('static', true);
|
||||
|
||||
this.setHD(true);
|
||||
this.setAntiAliasing(false);
|
||||
@ -128,6 +131,17 @@ export class LayerGroup extends Container implements IAnimateFrame {
|
||||
binder.bindThis();
|
||||
}
|
||||
|
||||
protected render(canvas: MotaOffscreenCanvas2D): void {
|
||||
const { ctx } = canvas;
|
||||
|
||||
this.sortedChildren.forEach(v => {
|
||||
if (v.hidden) return;
|
||||
ctx.save();
|
||||
v.renderContent(canvas, this.camera);
|
||||
ctx.restore();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加渲染拓展,可以将渲染拓展理解为一类插件,通过指定的函数在对应时刻执行一些函数,
|
||||
* 来达到执行自己想要的功能的效果。例如样板自带的勇士渲染、伤害渲染等都由此实现。
|
||||
@ -633,7 +647,7 @@ export class Layer extends Container {
|
||||
protected backMap: MotaOffscreenCanvas2D = new MotaOffscreenCanvas2D();
|
||||
|
||||
/** 最终渲染至的Sprite */
|
||||
main: Sprite = new Sprite('static', false);
|
||||
main: Sprite = new Sprite('absolute', false, true);
|
||||
|
||||
/** 渲染的层 */
|
||||
layer?: FloorLayer;
|
||||
@ -670,7 +684,7 @@ export class Layer extends Container {
|
||||
moving: Set<LayerMovingRenderable> = new Set();
|
||||
|
||||
constructor() {
|
||||
super('absolute', false);
|
||||
super('absolute', false, true);
|
||||
|
||||
// this.setHD(false);
|
||||
this.setAntiAliasing(false);
|
||||
|
390
src/core/render/preset/viewport.ts
Normal file
390
src/core/render/preset/viewport.ts
Normal file
@ -0,0 +1,390 @@
|
||||
import { logger } from '@/core/common/logger';
|
||||
import { HeroRenderer } from './hero';
|
||||
import { ILayerGroupRenderExtends, LayerGroup } from './layer';
|
||||
import { Transform } from '../transform';
|
||||
import { LayerGroupFloorBinder } from './floor';
|
||||
import { hyper, TimingFn } from 'mutate-animate';
|
||||
import { RenderAdapter } from '../adapter';
|
||||
|
||||
export class FloorViewport implements ILayerGroupRenderExtends {
|
||||
id: string = 'viewport';
|
||||
|
||||
group!: LayerGroup;
|
||||
hero!: HeroRenderer;
|
||||
transform!: Transform;
|
||||
binder!: LayerGroupFloorBinder;
|
||||
|
||||
/** 是否启用视角控制拓展 */
|
||||
enabled: boolean = true;
|
||||
|
||||
/** 渐变的速率曲线 */
|
||||
transitionFn: TimingFn = hyper('sin', 'out');
|
||||
/** 加减速的速率曲线 */
|
||||
movingEaseFn: TimingFn = t => t ** 2;
|
||||
|
||||
/** 突变时的渐变时长 */
|
||||
transitionTime: number = 600;
|
||||
|
||||
/** 当前视角移动速度 */
|
||||
private speedX: number = 0;
|
||||
private speedY: number = 0;
|
||||
/** X方向移动状态,0表示静止,1表示加速过程,2表示匀速过程,3表示减速过程 */
|
||||
private movingStatusX: 0 | 1 | 2 | 3 = 0;
|
||||
/** X方向加减速过程进度 */
|
||||
private movingEaseProgressX: number = 0;
|
||||
/** Y方向移动状态,0表示静止,1表示加速过程,2表示匀速过程,3表示减速过程 */
|
||||
private movingStatusY: 0 | 1 | 2 | 3 = 0;
|
||||
/** Y方向加减速过程进度 */
|
||||
private movingEaseProgressY: number = 0;
|
||||
/** X方向移动结束坐标 */
|
||||
private movingEndX: number = 0;
|
||||
/** X方向移动结束坐标 */
|
||||
private movingEndY: number = 0;
|
||||
/** X方向进入第一阶段的时刻 */
|
||||
private movingAccX: number = 0;
|
||||
/** Y方向进入第一阶段的时刻 */
|
||||
private movingAccY: number = 0;
|
||||
/** X方向进入第二阶段的时刻 */
|
||||
private movingConstantX: number = 0;
|
||||
/** Y方向进入第二阶段的时刻 */
|
||||
private movingConstantY: number = 0;
|
||||
/** X方向进入第三阶段的时刻 */
|
||||
private movingDeaccX: number = 0;
|
||||
/** Y方向进入第三阶段的时刻 */
|
||||
private movingDeaccY: number = 0;
|
||||
/** X方向进入第一阶段的横坐标 */
|
||||
private movingAccPosX: number = 0;
|
||||
/** Y方向进入第一阶段的横坐标 */
|
||||
private movingAccPosY: number = 0;
|
||||
/** X方向进入第二阶段的横坐标 */
|
||||
private movingConstantPosX: number = 0;
|
||||
/** Y方向进入第二阶段的横坐标 */
|
||||
private movingConstantPosY: number = 0;
|
||||
/** X方向进入第三阶段的横坐标 */
|
||||
private movingDeaccPosX: number = 0;
|
||||
/** Y方向进入第三阶段的横坐标 */
|
||||
private movingDeaccPosY: number = 0;
|
||||
/** X方向进入第一阶段的进度 */
|
||||
private movingAccProgressX: number = 0;
|
||||
/** Y方向进入第一阶段的进度 */
|
||||
private movingAccProgressY: number = 0;
|
||||
/** X方向进入第三阶段的进度 */
|
||||
private movingDeaccProgressX: number = 0;
|
||||
/** Y方向进入第三阶段的进度 */
|
||||
private movingDeaccProgressY: number = 0;
|
||||
/** 移动的加减速时长 */
|
||||
private movingEaseTime: number = 0;
|
||||
|
||||
/** 当前视角位置 */
|
||||
private nx: number = 0;
|
||||
private ny: number = 0;
|
||||
|
||||
/** 委托ticker */
|
||||
private delegation: number = -1;
|
||||
/** 渐变委托ticker */
|
||||
private transition: number = -1;
|
||||
/** 移动委托ticker */
|
||||
private moving: number = -1;
|
||||
/** 是否在渐变过程中 */
|
||||
private inTransition: boolean = false;
|
||||
/** 是否在移动过程中 */
|
||||
private inMoving: boolean = false;
|
||||
|
||||
/**
|
||||
* 禁用自动视角控制
|
||||
*/
|
||||
disable() {
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用自动视角控制
|
||||
*/
|
||||
enable() {
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入视角的目标位置,将其限定在地图范围内后返回
|
||||
* @param x 图格横坐标
|
||||
* @param y 图格纵坐标
|
||||
*/
|
||||
getBoundedPosition(x: number, y: number) {
|
||||
const width = core._WIDTH_;
|
||||
const height = core._HEIGHT_;
|
||||
const minX = (width - 1) / 2;
|
||||
const minY = (height - 1) / 2;
|
||||
const floor = core.status.maps[this.binder.getFloor()];
|
||||
const maxX = floor.width - minX - 1;
|
||||
const maxY = floor.height - minY - 1;
|
||||
|
||||
// return { x, y };
|
||||
return { x: core.clamp(x, minX, maxX), y: core.clamp(y, minY, maxY) };
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置视角位置
|
||||
* @param x 目标图格横坐标
|
||||
* @param y 目标图格纵坐标
|
||||
*/
|
||||
setPosition(x: number, y: number) {
|
||||
const { x: nx, y: ny } = this.getBoundedPosition(x, y);
|
||||
this.group.removeTicker(this.transition, false);
|
||||
this.nx = nx;
|
||||
this.ny = ny;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当勇士通过移动改变至指定位置时移动视角
|
||||
* @param x 目标图格横坐标
|
||||
* @param y 目标图格纵坐标
|
||||
*/
|
||||
moveTo(x: number, y: number) {
|
||||
const { x: nx, y: ny } = this.getBoundedPosition(x, y);
|
||||
if (this.inTransition) {
|
||||
const distance = Math.hypot(this.nx - nx, this.ny - ny);
|
||||
const time = core.clamp(distance * 200, 200, 600);
|
||||
this.createTransition(nx, ny, time);
|
||||
} else {
|
||||
this.createTransition(nx, ny, 200);
|
||||
// const moveSpeed = 1000 / this.hero.speed;
|
||||
// this.speedX = moveSpeed;
|
||||
// this.speedY = moveSpeed;
|
||||
// this.movingEndX = x;
|
||||
// this.movingEndY = y;
|
||||
// this.movingEaseTime = moveSpeed * 2;
|
||||
// this.processMoving(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private processMoving(x: number, y: number) {
|
||||
this.movingEndX = x;
|
||||
this.movingEndY = y;
|
||||
if (!this.inMoving) {
|
||||
this.movingStatusX = 0;
|
||||
this.movingEaseProgressX = 0;
|
||||
this.movingStatusY = 0;
|
||||
this.movingEaseProgressY = 0;
|
||||
this.inMoving = true;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当勇士位置突变至指定位置时移动视角
|
||||
* @param x 目标图格横坐标
|
||||
* @param y 目标图格纵坐标
|
||||
*/
|
||||
mutateTo(x: number, y: number) {
|
||||
const { x: nx, y: ny } = this.getBoundedPosition(x, y);
|
||||
this.createTransition(nx, ny, this.transitionTime);
|
||||
}
|
||||
|
||||
private createTransition(x: number, y: number, time: number) {
|
||||
const start = Date.now();
|
||||
const end = start + time;
|
||||
const sx = this.nx;
|
||||
const sy = this.ny;
|
||||
const dx = x - sx;
|
||||
const dy = y - sy;
|
||||
this.speedX = 0;
|
||||
this.speedY = 0;
|
||||
|
||||
this.inTransition = true;
|
||||
this.group.removeTicker(this.transition, false);
|
||||
this.transition = this.group.delegateTicker(
|
||||
() => {
|
||||
const now = Date.now();
|
||||
if (now >= end) {
|
||||
this.group.removeTicker(this.transition, true);
|
||||
return;
|
||||
}
|
||||
const progress = this.transitionFn((now - start) / time);
|
||||
const tx = dx * progress;
|
||||
const ty = dy * progress;
|
||||
this.nx = tx + sx;
|
||||
this.ny = ty + sy;
|
||||
},
|
||||
time,
|
||||
() => {
|
||||
this.nx = x;
|
||||
this.ny = y;
|
||||
this.inTransition = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private createMoving() {
|
||||
this.moving = this.group.delegateTicker(() => {
|
||||
const nx = this.nx;
|
||||
const ny = this.ny;
|
||||
const now = Date.now();
|
||||
const dx = Math.sign(this.movingEndX - nx);
|
||||
const dy = Math.sign(this.movingEndY - ny);
|
||||
const fn = this.movingEaseFn;
|
||||
// 进行进度判断
|
||||
if (this.movingEndX !== nx && this.movingStatusX === 0) {
|
||||
this.movingStatusX = 1;
|
||||
this.movingAccX = now;
|
||||
this.movingAccProgressX = this.movingEaseProgressX;
|
||||
this.movingAccPosX = nx - fn(this.movingAccProgressX) * dx;
|
||||
}
|
||||
if (this.movingEndY !== ny && this.movingStatusY === 0) {
|
||||
this.movingEaseProgressY = 1;
|
||||
this.movingAccY = now;
|
||||
this.movingAccProgressY = this.movingEaseProgressY;
|
||||
this.movingAccPosY = ny - fn(this.movingAccProgressY) * dy;
|
||||
}
|
||||
if (
|
||||
Math.abs(this.movingEndX - nx) <= 1 &&
|
||||
this.movingStatusX !== 3
|
||||
) {
|
||||
this.movingStatusX = 3;
|
||||
this.movingDeaccX = now;
|
||||
this.movingDeaccProgressX = this.movingEaseProgressX;
|
||||
this.movingDeaccPosX =
|
||||
nx - (fn(this.movingDeaccProgressX) + 1) * dx;
|
||||
}
|
||||
if (
|
||||
Math.abs(this.movingEndY - ny) <= 1 &&
|
||||
this.movingStatusY !== 3
|
||||
) {
|
||||
this.movingStatusY = 3;
|
||||
this.movingDeaccY = now;
|
||||
this.movingDeaccProgressY = this.movingEaseProgressY;
|
||||
this.movingDeaccPosY =
|
||||
ny - (fn(this.movingDeaccProgressY) + 1) * dy;
|
||||
}
|
||||
if (this.movingEaseProgressX >= 1 && this.movingStatusX === 1) {
|
||||
this.movingStatusX = 2;
|
||||
this.movingConstantX = now;
|
||||
this.movingConstantPosX = nx;
|
||||
}
|
||||
if (this.movingEaseProgressY >= 1 && this.movingStatusY === 1) {
|
||||
this.movingStatusY = 2;
|
||||
this.movingConstantY = now;
|
||||
this.movingConstantPosY = ny;
|
||||
}
|
||||
if (this.movingEaseProgressX <= 0 && this.movingStatusX === 3) {
|
||||
this.nx = this.movingEndX;
|
||||
this.movingStatusX = 0;
|
||||
this.movingEaseProgressX = 0;
|
||||
}
|
||||
if (this.movingEaseProgressY <= 0 && this.movingStatusY === 3) {
|
||||
this.ny = this.movingEndY;
|
||||
this.movingStatusY = 0;
|
||||
this.movingEaseProgressY = 0;
|
||||
}
|
||||
|
||||
// 平滑视角位置计算
|
||||
if (this.movingEaseProgressX === 1) {
|
||||
// 加速阶段
|
||||
this.movingEaseProgressX =
|
||||
(now - this.movingAccX) / this.movingEaseTime;
|
||||
const tx = fn(this.movingEaseProgressX) * dx;
|
||||
this.nx = this.movingAccPosX + tx;
|
||||
} else if (this.movingEaseProgressX === 2) {
|
||||
// 匀速阶段
|
||||
const time = now - this.movingConstantX;
|
||||
this.nx = this.movingConstantPosX + time * this.speedX * dx;
|
||||
} else if (this.movingEaseProgressX === 3) {
|
||||
// 减速阶段
|
||||
this.movingEaseProgressX =
|
||||
1 - (now - this.movingDeaccX) / this.movingEaseTime;
|
||||
const tx = fn(this.movingEaseProgressX) * dx;
|
||||
this.nx = this.movingDeaccPosX + tx;
|
||||
}
|
||||
|
||||
if (this.movingEaseProgressY === 1) {
|
||||
// 加速阶段
|
||||
this.movingEaseProgressY =
|
||||
(now - this.movingAccY) / this.movingEaseTime;
|
||||
const ty = fn(this.movingEaseProgressY) * dy;
|
||||
this.ny = this.movingAccPosY + ty;
|
||||
} else if (this.movingEaseProgressY === 2) {
|
||||
// 匀速阶段
|
||||
const time = now - this.movingConstantY;
|
||||
this.ny = this.movingConstantPosY + time * this.speedY * dy;
|
||||
} else if (this.movingEaseProgressY === 3) {
|
||||
// 减速阶段
|
||||
this.movingEaseProgressY =
|
||||
1 - (now - this.movingDeaccY) / this.movingEaseTime;
|
||||
const ty = fn(this.movingEaseProgressY) * dy;
|
||||
this.ny = this.movingDeaccPosY + ty;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private create() {
|
||||
let nx = this.nx;
|
||||
let ny = this.ny;
|
||||
const halfWidth = core._PX_ / 2;
|
||||
const halfHeight = core._PY_ / 2;
|
||||
this.delegation = this.group.delegateTicker(() => {
|
||||
if (this.nx === nx && this.ny === ny) return;
|
||||
const cell = this.group.cellSize;
|
||||
const half = cell / 2;
|
||||
nx = this.nx;
|
||||
ny = this.ny;
|
||||
const ox = nx * cell;
|
||||
const oy = ny * cell;
|
||||
core.bigmap.offsetX = ox;
|
||||
core.bigmap.offsetY = oy;
|
||||
|
||||
this.group.camera.setTranslate(
|
||||
-ox + halfWidth - half,
|
||||
-oy + halfHeight - half
|
||||
);
|
||||
this.group.update(this.group);
|
||||
});
|
||||
// this.createMoving();
|
||||
}
|
||||
|
||||
awake(group: LayerGroup): void {
|
||||
this.group = group;
|
||||
this.transform = group.transform;
|
||||
const ex1 = group.getLayer('event')?.getExtends('floor-hero');
|
||||
const ex2 = group.getExtends('floor-binder');
|
||||
if (
|
||||
ex1 instanceof HeroRenderer &&
|
||||
ex2 instanceof LayerGroupFloorBinder
|
||||
) {
|
||||
this.hero = ex1;
|
||||
this.binder = ex2;
|
||||
this.create();
|
||||
adapter.add(this);
|
||||
} else {
|
||||
logger.error(
|
||||
15,
|
||||
`Viewport extends needs 'floor-hero' extends as dependency.`
|
||||
);
|
||||
group.removeExtends('viewport');
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(group: LayerGroup): void {
|
||||
group.removeTicker(this.delegation);
|
||||
group.removeTicker(this.transition);
|
||||
group.removeTicker(this.moving);
|
||||
adapter.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
const adapter = new RenderAdapter<FloorViewport>('viewport');
|
||||
adapter.receive('mutateTo', (item, x, y) => {
|
||||
item.mutateTo(x, y);
|
||||
return Promise.resolve();
|
||||
});
|
||||
adapter.receive('moveTo', (item, x, y) => {
|
||||
item.moveTo(x, y);
|
||||
return Promise.resolve();
|
||||
});
|
||||
adapter.receive('setPosition', (item, x, y) => {
|
||||
item.setPosition(x, y);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
const hook = Mota.require('var', 'hook');
|
||||
hook.on('changingFloor', (_, loc) => {
|
||||
adapter.all('setPosition', loc.x, loc.y);
|
||||
});
|
@ -19,8 +19,12 @@ export class Sprite<E extends ESpriteEvent = ESpriteEvent> extends RenderItem<
|
||||
* @param type 渲染模式,absolute表示绝对位置,不会跟随自身的Transform改变
|
||||
* @param cache 是否启用缓存机制
|
||||
*/
|
||||
constructor(type: RenderItemPosition = 'static', cache: boolean = true) {
|
||||
super(type, cache);
|
||||
constructor(
|
||||
type: RenderItemPosition = 'static',
|
||||
cache: boolean = true,
|
||||
fall: boolean = false
|
||||
) {
|
||||
super(type, cache, fall);
|
||||
this.type = type;
|
||||
this.renderFn = () => {};
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ export class Portal extends Sprite {
|
||||
private delegation: number;
|
||||
|
||||
constructor() {
|
||||
super('static', false);
|
||||
super('static', false, true);
|
||||
|
||||
this.particleSetting = mainSetting.getSetting('fx.portalParticle')!;
|
||||
|
||||
|
@ -10,6 +10,7 @@ import { BluePalace } from '@/game/mechanism/misc';
|
||||
import { backDir } from './utils';
|
||||
import type { TimingFn } from 'mutate-animate';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import type { FloorViewport } from '@/core/render/preset/viewport';
|
||||
|
||||
// 向后兼容用,会充当两个版本间过渡的作用
|
||||
|
||||
@ -18,6 +19,7 @@ interface Adapters {
|
||||
'door-animate'?: RenderAdapter<LayerDoorAnimate>;
|
||||
animate?: RenderAdapter<LayerGroupAnimate>;
|
||||
layer?: RenderAdapter<Layer>;
|
||||
viewport?: RenderAdapter<FloorViewport>;
|
||||
}
|
||||
|
||||
interface MoveEvent {
|
||||
@ -38,11 +40,13 @@ export function init() {
|
||||
const doorAnimate = Adapter.get<LayerDoorAnimate>('door-animate');
|
||||
const animate = Adapter.get<LayerGroupAnimate>('animate');
|
||||
const layer = Adapter.get<Layer>('layer');
|
||||
const viewport = Adapter.get<FloorViewport>('viewport');
|
||||
|
||||
adapters['hero-adapter'] = hero;
|
||||
adapters['door-animate'] = doorAnimate;
|
||||
adapters['animate'] = animate;
|
||||
adapters['layer'] = layer;
|
||||
adapters['viewport'] = viewport;
|
||||
}
|
||||
|
||||
let moving: boolean = false;
|
||||
@ -193,6 +197,17 @@ export function init() {
|
||||
}
|
||||
|
||||
stepEnding = adapter.all('move', moveDir);
|
||||
if (portal && portalData) {
|
||||
adapters.viewport?.all(
|
||||
'mutateTo',
|
||||
portalData.x,
|
||||
portalData.y
|
||||
);
|
||||
} else {
|
||||
const { nx, ny } = getNextLoc();
|
||||
adapters.viewport?.all('moveTo', nx, ny);
|
||||
}
|
||||
|
||||
await stepEnding;
|
||||
|
||||
moveEmit.emit('stepEnd');
|
||||
@ -260,11 +275,13 @@ export function init() {
|
||||
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;
|
||||
} else if (!noPass) {
|
||||
const { nx, ny } = getNextLoc();
|
||||
core.setHeroLoc('x', nx, true);
|
||||
@ -929,6 +946,7 @@ export function init() {
|
||||
if (moving) return;
|
||||
const sx = core.getHeroLoc('x');
|
||||
const sy = core.getHeroLoc('y');
|
||||
adapters.viewport?.all('mutateTo', ex, ey);
|
||||
|
||||
const locked = core.status.lockControl;
|
||||
core.lockControl();
|
||||
@ -956,6 +974,18 @@ export function init() {
|
||||
core.setHeroLoc('y', ey);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
// ----- 视角处理
|
||||
|
||||
////// 瞬间移动 //////
|
||||
control.prototype.moveDirectly = function (
|
||||
destX: number,
|
||||
destY: number,
|
||||
ignoreSteps: number
|
||||
) {
|
||||
adapters.viewport?.all('mutateTo', destX, destY);
|
||||
return this.controldata.moveDirectly(destX, destY, ignoreSteps);
|
||||
};
|
||||
});
|
||||
|
||||
loading.once('loaded', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user