mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-06-08 16:27:58 +08:00
refactor: 移动的视角变化
This commit is contained in:
parent
d8439d3f2a
commit
2bf0fbe781
@ -14,13 +14,14 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
|
|
||||||
/** 是否启用视角控制拓展 */
|
/** 是否启用视角控制拓展 */
|
||||||
enabled: boolean = true;
|
enabled: boolean = true;
|
||||||
|
/** 是否自动限定视角范围至地图范围 */
|
||||||
|
boundX: boolean = true;
|
||||||
|
boundY: boolean = true;
|
||||||
|
|
||||||
/** 渐变的速率曲线 */
|
/** 渐变的速率曲线 */
|
||||||
transitionFn: TimingFn = hyper('sec', 'out');
|
transitionFn: TimingFn = hyper('sin', 'out');
|
||||||
/** 瞬移的速率曲线 */
|
/** 瞬移的速率曲线 */
|
||||||
mutateFn: TimingFn = hyper('sin', 'out');
|
mutateFn: TimingFn = hyper('sin', 'out');
|
||||||
/** 加减速的速率曲线 */
|
|
||||||
movingEaseFn: TimingFn = t => t ** 2;
|
|
||||||
|
|
||||||
/** 突变时的渐变时长 */
|
/** 突变时的渐变时长 */
|
||||||
transitionTime: number = 600;
|
transitionTime: number = 600;
|
||||||
@ -28,11 +29,18 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
/** 当前视角位置 */
|
/** 当前视角位置 */
|
||||||
private nx: number = 0;
|
private nx: number = 0;
|
||||||
private ny: number = 0;
|
private ny: number = 0;
|
||||||
|
/** 移动时的偏移位置 */
|
||||||
|
private ox: number = 0;
|
||||||
|
private oy: number = 0;
|
||||||
|
/** 移动时的偏移最大值 */
|
||||||
|
private maxOffset: number = 1;
|
||||||
|
|
||||||
/** 委托ticker */
|
/** 委托ticker */
|
||||||
private delegation: number = -1;
|
private delegation: number = -1;
|
||||||
/** 渐变委托ticker */
|
/** 渐变委托ticker */
|
||||||
private transition: number = -1;
|
private transition: number = -1;
|
||||||
|
/** 移动的委托ticker */
|
||||||
|
private moveDelegation: number = -1;
|
||||||
/** 移动委托ticker */
|
/** 移动委托ticker */
|
||||||
private moving: number = -1;
|
private moving: number = -1;
|
||||||
/** 是否在渐变过程中 */
|
/** 是否在渐变过程中 */
|
||||||
@ -40,6 +48,9 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
/** 是否在移动过程中 */
|
/** 是否在移动过程中 */
|
||||||
private inMoving: boolean = false;
|
private inMoving: boolean = false;
|
||||||
|
|
||||||
|
/** 移动的监听函数 */
|
||||||
|
private movingFramer?: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 禁用自动视角控制
|
* 禁用自动视角控制
|
||||||
*/
|
*/
|
||||||
@ -63,12 +74,23 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
this.mutateTo(x, y);
|
this.mutateTo(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否自动限定视角范围至地图范围
|
||||||
|
* @param boundX 是否自动限定水平视角范围
|
||||||
|
* @param boundY 是否自动限定竖直视角范围
|
||||||
|
*/
|
||||||
|
setAutoBound(boundX: boolean = this.boundX, boundY: boolean = this.boundY) {
|
||||||
|
this.boundX = boundX;
|
||||||
|
this.boundY = boundY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 传入视角的目标位置,将其限定在地图范围内后返回
|
* 传入视角的目标位置,将其限定在地图范围内后返回
|
||||||
* @param x 图格横坐标
|
* @param x 图格横坐标
|
||||||
* @param y 图格纵坐标
|
* @param y 图格纵坐标
|
||||||
*/
|
*/
|
||||||
getBoundedPosition(x: number, y: number) {
|
getBoundedPosition(x: number, y: number) {
|
||||||
|
if (!this.boundX && !this.boundY) return { x, y };
|
||||||
const width = core._WIDTH_;
|
const width = core._WIDTH_;
|
||||||
const height = core._HEIGHT_;
|
const height = core._HEIGHT_;
|
||||||
const minX = (width - 1) / 2;
|
const minX = (width - 1) / 2;
|
||||||
@ -77,8 +99,10 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
const maxX = floor.width - minX - 1;
|
const maxX = floor.width - minX - 1;
|
||||||
const maxY = floor.height - minY - 1;
|
const maxY = floor.height - minY - 1;
|
||||||
|
|
||||||
// return { x, y };
|
return {
|
||||||
return { x: core.clamp(x, minX, maxX), y: core.clamp(y, minY, maxY) };
|
x: this.boundX ? core.clamp(x, minX, maxX) : x,
|
||||||
|
y: this.boundY ? core.clamp(y, minY, maxY) : y
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,6 +118,22 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
this.ny = ny;
|
this.ny = ny;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始移动
|
||||||
|
*/
|
||||||
|
startMove() {
|
||||||
|
if (this.inMoving) return;
|
||||||
|
this.inMoving = true;
|
||||||
|
this.createMoveTransition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束移动
|
||||||
|
*/
|
||||||
|
endMove() {
|
||||||
|
this.inMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当勇士通过移动改变至指定位置时移动视角
|
* 当勇士通过移动改变至指定位置时移动视角
|
||||||
* @param x 目标图格横坐标
|
* @param x 目标图格横坐标
|
||||||
@ -106,11 +146,83 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
const distance = Math.hypot(this.nx - nx, this.ny - ny);
|
const distance = Math.hypot(this.nx - nx, this.ny - ny);
|
||||||
const t = core.clamp(distance * time, time, time * 3);
|
const t = core.clamp(distance * time, time, time * 3);
|
||||||
this.createTransition(nx, ny, t, this.transitionFn);
|
this.createTransition(nx, ny, t, this.transitionFn);
|
||||||
} else {
|
|
||||||
this.createTransition(nx, ny, time, this.transitionFn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createMoveTransition() {
|
||||||
|
let xTarget: number = 0;
|
||||||
|
let yTarget: number = 0;
|
||||||
|
let xStart: number = this.ox;
|
||||||
|
let yStart: number = this.oy;
|
||||||
|
let xStartTime: number = Date.now();
|
||||||
|
let yStartTime: number = Date.now();
|
||||||
|
let ending: boolean = false;
|
||||||
|
// 这个数等于 sinh(2),用这个数的话,可以正好在刚开始移动的时候达到1的斜率,效果会比较好
|
||||||
|
const transitionTime = this.hero.speed * 3.626860407847019;
|
||||||
|
|
||||||
|
const setTargetX = (x: number, time: number) => {
|
||||||
|
if (x === xTarget) return;
|
||||||
|
xTarget = x;
|
||||||
|
xStart = this.ox;
|
||||||
|
xStartTime = time;
|
||||||
|
};
|
||||||
|
const setTargetY = (y: number, time: number) => {
|
||||||
|
if (y === yTarget) return;
|
||||||
|
yTarget = y;
|
||||||
|
yStart = this.oy;
|
||||||
|
yStartTime = time;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.movingFramer) {
|
||||||
|
this.hero.off('moveTick', this.movingFramer);
|
||||||
|
}
|
||||||
|
this.movingFramer = () => {
|
||||||
|
const now = Date.now();
|
||||||
|
if (!this.inMoving && !ending) {
|
||||||
|
setTargetX(0, now);
|
||||||
|
setTargetY(0, now);
|
||||||
|
ending = true;
|
||||||
|
}
|
||||||
|
if (!ending) {
|
||||||
|
const dir = this.hero.stepDir;
|
||||||
|
const { x, y } = core.utils.scan2[dir];
|
||||||
|
if (x !== 0) setTargetX(-x * this.maxOffset, now);
|
||||||
|
if (y !== 0) setTargetY(-y * this.maxOffset, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hero.renderable) return;
|
||||||
|
|
||||||
|
this.nx = this.hero.renderable.x;
|
||||||
|
this.ny = this.hero.renderable.y;
|
||||||
|
|
||||||
|
if (ending) {
|
||||||
|
if (this.ox === xTarget && this.oy == yTarget) {
|
||||||
|
this.group.removeTicker(this.moveDelegation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.ox !== xTarget) {
|
||||||
|
const progress = (now - xStartTime) / transitionTime;
|
||||||
|
if (progress > 1) {
|
||||||
|
this.ox = xTarget;
|
||||||
|
} else {
|
||||||
|
const p = this.transitionFn(progress);
|
||||||
|
this.ox = (xTarget - xStart) * p + xStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.oy !== yTarget) {
|
||||||
|
const progress = (now - yStartTime) / transitionTime;
|
||||||
|
if (progress > 1) {
|
||||||
|
this.oy = yTarget;
|
||||||
|
} else {
|
||||||
|
const p = this.transitionFn(progress);
|
||||||
|
this.oy = (yTarget - yStart) * p + yStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.hero.on('moveTick', this.movingFramer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当勇士位置突变至指定位置时移动视角
|
* 当勇士位置突变至指定位置时移动视角
|
||||||
* @param x 目标图格横坐标
|
* @param x 目标图格横坐标
|
||||||
@ -157,21 +269,33 @@ export class FloorViewport implements ILayerGroupRenderExtends {
|
|||||||
private create() {
|
private create() {
|
||||||
let nx = this.nx;
|
let nx = this.nx;
|
||||||
let ny = this.ny;
|
let ny = this.ny;
|
||||||
|
let ox = this.ox;
|
||||||
|
let oy = this.oy;
|
||||||
const halfWidth = core._PX_ / 2;
|
const halfWidth = core._PX_ / 2;
|
||||||
const halfHeight = core._PY_ / 2;
|
const halfHeight = core._PY_ / 2;
|
||||||
this.delegation = this.group.delegateTicker(() => {
|
this.delegation = this.group.delegateTicker(() => {
|
||||||
if (!this.enabled) return;
|
if (!this.enabled) return;
|
||||||
if (this.nx === nx && this.ny === ny) return;
|
if (
|
||||||
|
this.nx === nx &&
|
||||||
|
this.ny === ny &&
|
||||||
|
this.ox === ox &&
|
||||||
|
this.oy === oy
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const cell = this.group.cellSize;
|
const cell = this.group.cellSize;
|
||||||
const half = cell / 2;
|
const half = cell / 2;
|
||||||
nx = this.nx;
|
nx = this.nx;
|
||||||
ny = this.ny;
|
ny = this.ny;
|
||||||
const ox = this.nx * cell - halfWidth + half;
|
ox = this.ox;
|
||||||
const oy = this.ny * cell - halfHeight + half;
|
oy = this.oy;
|
||||||
core.bigmap.offsetX = ox;
|
const { x: bx, y: by } = this.getBoundedPosition(nx + ox, ny + oy);
|
||||||
core.bigmap.offsetY = oy;
|
const rx = bx * cell - halfWidth + half;
|
||||||
|
const ry = by * cell - halfHeight + half;
|
||||||
|
core.bigmap.offsetX = rx;
|
||||||
|
core.bigmap.offsetY = ry;
|
||||||
|
|
||||||
this.group.camera.setTranslate(-ox, -oy);
|
this.group.camera.setTranslate(-rx, -ry);
|
||||||
this.group.update(this.group);
|
this.group.update(this.group);
|
||||||
});
|
});
|
||||||
// this.createMoving();
|
// this.createMoving();
|
||||||
@ -222,6 +346,12 @@ adapter.receiveSync('disable', item => {
|
|||||||
adapter.receiveSync('enable', item => {
|
adapter.receiveSync('enable', item => {
|
||||||
item.enable();
|
item.enable();
|
||||||
});
|
});
|
||||||
|
adapter.receiveSync('startMove', item => {
|
||||||
|
item.startMove();
|
||||||
|
});
|
||||||
|
adapter.receiveSync('endMove', item => {
|
||||||
|
item.endMove();
|
||||||
|
});
|
||||||
|
|
||||||
const hook = Mota.require('var', 'hook');
|
const hook = Mota.require('var', 'hook');
|
||||||
hook.on('changingFloor', (_, loc) => {
|
hook.on('changingFloor', (_, loc) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user