mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-09 06:14:30 +08:00
refactor: 修复所有的循环引用
This commit is contained in:
1 parent
4fda246a9a
commit
23a8c0bf3a
82 files changed
+1015
-2087
No files matched your search
@@ -1,415 +0,0 @@
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import {
|
||||
FloorLayer,
|
||||
ILayerGroupRenderExtends,
|
||||
ILayerRenderExtends,
|
||||
Layer,
|
||||
LayerGroup,
|
||||
LayerMovingRenderable
|
||||
} from './layer';
|
||||
import { texture } from './cache';
|
||||
import { sleep } from 'mutate-animate';
|
||||
import { RenderAdapter } from '@motajs/render-core';
|
||||
|
||||
const { hook } = Mota.require('@user/data-base');
|
||||
|
||||
hook.on('setBlock', (x, y, floor, block) => {
|
||||
const isNow = floor === core.status.floorId;
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (floor === v.floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock('event', block, x, y);
|
||||
}
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.layer.layer === 'event') {
|
||||
if (v.floor === floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(block, x, y);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
hook.on('changingFloor', floor => {
|
||||
// 潜在隐患:如果putRenderData改成异步,那么会变成两帧后才能真正刷新并渲染
|
||||
// 考虑到楼层转换一般不会同时执行很多次,因此这里改为立刻更新
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (v.bindThisFloor) v.updateBindData();
|
||||
v.emit('floorChange', floor);
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.bindThisFloor) v.updateBindData();
|
||||
});
|
||||
});
|
||||
hook.on('setBgFgBlock', (name, number, x, y, floor) => {
|
||||
const isNow = floor === core.status.floorId;
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (floor === v.floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(name, number, x, y);
|
||||
}
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.layer.layer === name) {
|
||||
if (v.floor === floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(number, x, y);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface LayerGroupBinderEvent {
|
||||
update: [floor: FloorIds];
|
||||
setBlock: [x: number, y: number, floor: FloorIds, block: AllNumbers];
|
||||
floorChange: [floor: FloorIds];
|
||||
}
|
||||
|
||||
/**
|
||||
* 楼层绑定拓展,用于LayerGroup,将楼层数据传输到渲染系统。
|
||||
* 添加后,会自动在LayerGroup包含的子Layer上添加LayerFloorBinder拓展,用于后续处理。
|
||||
* 当移除这个拓展时,其附属的所有子拓展也会一并被移除。
|
||||
*/
|
||||
export class LayerGroupFloorBinder
|
||||
extends EventEmitter<LayerGroupBinderEvent>
|
||||
implements ILayerGroupRenderExtends
|
||||
{
|
||||
id: string = 'floor-binder';
|
||||
|
||||
bindThisFloor: boolean = true;
|
||||
floor?: FloorIds;
|
||||
group!: LayerGroup;
|
||||
|
||||
/** 附属的子LayerFloorBinder拓展 */
|
||||
layerBinders: Set<LayerFloorBinder> = new Set();
|
||||
|
||||
private needUpdate: boolean = false;
|
||||
|
||||
static activedBinder: Set<LayerGroupFloorBinder> = new Set();
|
||||
|
||||
/**
|
||||
* 绑定楼层为当前楼层,并跟随变化
|
||||
*/
|
||||
bindThis() {
|
||||
this.floor = void 0;
|
||||
this.bindThisFloor = true;
|
||||
this.layerBinders.forEach(v => v.bindThis());
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为指定楼层
|
||||
* @param floorId 楼层id
|
||||
*/
|
||||
bindFloor(floorId: FloorIds) {
|
||||
this.bindThisFloor = false;
|
||||
this.floor = floorId;
|
||||
this.layerBinders.forEach(v => v.bindFloor(floorId));
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在下一帧进行绑定数据更新
|
||||
*/
|
||||
updateBind() {
|
||||
if (this.needUpdate || !this.group) return;
|
||||
this.needUpdate = true;
|
||||
this.group.requestBeforeFrame(() => {
|
||||
this.needUpdate = false;
|
||||
this.updateBindData();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 立刻进行数据绑定更新
|
||||
*/
|
||||
updateBindData() {
|
||||
this.layerBinders.forEach(v => {
|
||||
v.updateBindData();
|
||||
});
|
||||
|
||||
const floor = this.getFloor();
|
||||
this.emit('update', floor);
|
||||
}
|
||||
|
||||
getFloor() {
|
||||
return this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置图块
|
||||
*/
|
||||
setBlock(layer: FloorLayer, block: AllNumbers, x: number, y: number) {
|
||||
const ex = this.group
|
||||
.getLayer(layer)
|
||||
?.getExtends('floor-binder') as LayerFloorBinder;
|
||||
if (!ex) return;
|
||||
ex.setBlock(block, x, y);
|
||||
|
||||
const floor = this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
this.emit('setBlock', x, y, floor, block);
|
||||
}
|
||||
|
||||
checkLayerExtends(layer: Layer) {
|
||||
const ex = layer.getExtends('floor-binder');
|
||||
|
||||
if (!ex) {
|
||||
const extend = new LayerFloorBinder(this);
|
||||
layer.extends(extend);
|
||||
this.layerBinders.add(extend);
|
||||
} else {
|
||||
if (ex instanceof LayerFloorBinder) {
|
||||
ex.setParent(this);
|
||||
this.layerBinders.add(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
awake(group: LayerGroup) {
|
||||
this.group = group;
|
||||
|
||||
for (const layer of group.layers.values()) {
|
||||
this.checkLayerExtends(layer);
|
||||
}
|
||||
LayerGroupFloorBinder.activedBinder.add(this);
|
||||
}
|
||||
|
||||
onLayerAdd(_group: LayerGroup, layer: Layer): void {
|
||||
this.checkLayerExtends(layer);
|
||||
}
|
||||
|
||||
onDestroy(group: LayerGroup) {
|
||||
LayerGroupFloorBinder.activedBinder.delete(this);
|
||||
group.layers.forEach(v => {
|
||||
v.removeExtends('floor-binder');
|
||||
});
|
||||
this.removeAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 楼层绑定拓展,用于Layer的楼层渲染。
|
||||
* 注意,如果目标Layer是LayerGroup的子元素,那么会自动检测父元素是否包含LayerGroupFloorBinder拓展,
|
||||
* 如果包含,那么会自动将此拓展附加至父元素的拓展。当父元素的拓展被移除时,此拓展也会一并被移除。
|
||||
*/
|
||||
export class LayerFloorBinder implements ILayerRenderExtends {
|
||||
id: string = 'floor-binder';
|
||||
|
||||
parent?: LayerGroupFloorBinder;
|
||||
layer!: Layer;
|
||||
bindThisFloor: boolean = true;
|
||||
floor?: FloorIds;
|
||||
|
||||
static listenedBinder: Set<LayerFloorBinder> = new Set();
|
||||
|
||||
private needUpdate: boolean = false;
|
||||
|
||||
constructor(parent?: LayerGroupFloorBinder) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为当前楼层,并跟随变化
|
||||
*/
|
||||
bindThis() {
|
||||
this.floor = void 0;
|
||||
this.bindThisFloor = true;
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为指定楼层
|
||||
* @param floorId 楼层id
|
||||
*/
|
||||
bindFloor(floorId: FloorIds) {
|
||||
this.bindThisFloor = false;
|
||||
this.floor = floorId;
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
getFloor() {
|
||||
return this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置这个拓展附属至的父拓展(LayerGroupFloorBinder拓展)
|
||||
* @param parent 父拓展
|
||||
*/
|
||||
setParent(parent?: LayerGroupFloorBinder) {
|
||||
this.parent = parent;
|
||||
this.checkListen();
|
||||
}
|
||||
|
||||
private checkListen() {
|
||||
if (this.parent) LayerFloorBinder.listenedBinder.delete(this);
|
||||
else LayerFloorBinder.listenedBinder.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在下一帧进行绑定数据更新
|
||||
*/
|
||||
updateBind() {
|
||||
if (this.needUpdate) return;
|
||||
this.needUpdate = true;
|
||||
this.layer.requestBeforeFrame(() => {
|
||||
this.needUpdate = false;
|
||||
this.updateBindData();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置图块
|
||||
*/
|
||||
setBlock(block: AllNumbers, x: number, y: number) {
|
||||
this.layer.putRenderData([block], 1, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* 立刻更新绑定数据,而非下一帧
|
||||
*/
|
||||
updateBindData() {
|
||||
const floor = this.getFloor();
|
||||
if (!floor) return;
|
||||
core.extractBlocks(floor);
|
||||
const map = core.status.maps[floor];
|
||||
this.layer.setMapSize(map.width, map.height);
|
||||
const image = core.status.maps[this.getFloor()].images;
|
||||
if (this.layer.layer === 'event') {
|
||||
const m = map.map;
|
||||
this.layer.putRenderData(m.flat(), map.width, 0, 0);
|
||||
} else {
|
||||
const m = core.maps._getBgFgMapArray(this.layer.layer!, floor);
|
||||
this.layer.putRenderData(m.flat(), map.width, 0, 0);
|
||||
}
|
||||
if (this.layer.layer === 'bg') {
|
||||
// 别忘了背景图块
|
||||
this.layer.setBackground(texture.idNumberMap[map.defaultGround]);
|
||||
}
|
||||
const toDraw = image?.filter(v => v.canvas === this.layer.layer);
|
||||
this.layer.setFloorImage(toDraw ?? []);
|
||||
}
|
||||
|
||||
awake(layer: Layer) {
|
||||
this.layer = layer;
|
||||
if (!this.parent) {
|
||||
const group = layer.parent;
|
||||
if (group instanceof LayerGroup) {
|
||||
const ex = group.getExtends('floor-binder');
|
||||
if (ex instanceof LayerGroupFloorBinder) {
|
||||
ex.checkLayerExtends(layer);
|
||||
this.parent = ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkListen();
|
||||
}
|
||||
|
||||
onDestroy(_layer: Layer) {
|
||||
LayerFloorBinder.listenedBinder.delete(this);
|
||||
this.parent?.layerBinders.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
interface DoorAnimateRenderable {
|
||||
renderable: LayerMovingRenderable;
|
||||
count: number;
|
||||
perTime: number;
|
||||
}
|
||||
|
||||
export class LayerDoorAnimate implements ILayerRenderExtends {
|
||||
id: string = 'door-animate';
|
||||
|
||||
layer!: Layer;
|
||||
|
||||
private moving: Set<LayerMovingRenderable> = new Set();
|
||||
|
||||
private getRenderable(block: Block): DoorAnimateRenderable | null {
|
||||
const { x, y, id } = block;
|
||||
const renderable = texture.getRenderable(id);
|
||||
if (!renderable) return null;
|
||||
const image = renderable.autotile
|
||||
? renderable.image[0]
|
||||
: renderable.image;
|
||||
const time = block.event.doorInfo?.time ?? 160;
|
||||
const frame = renderable.render.length;
|
||||
const perTime = time / frame;
|
||||
|
||||
const data: LayerMovingRenderable = {
|
||||
x,
|
||||
y,
|
||||
zIndex: y,
|
||||
image,
|
||||
autotile: false,
|
||||
animate: 0,
|
||||
frame,
|
||||
bigImage: false,
|
||||
render: renderable.render,
|
||||
alpha: 1
|
||||
};
|
||||
return { renderable: data, count: frame, perTime };
|
||||
}
|
||||
|
||||
/**
|
||||
* 开门
|
||||
* @param block 图块信息
|
||||
*/
|
||||
async openDoor(block: Block) {
|
||||
const renderable = this.getRenderable(block);
|
||||
if (!renderable) return Promise.reject();
|
||||
const { renderable: data, count: frame, perTime } = renderable;
|
||||
data.animate = 0;
|
||||
this.moving.add(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
|
||||
let now = 0;
|
||||
while (now < frame) {
|
||||
await sleep(perTime);
|
||||
data.animate = ++now;
|
||||
this.layer.update(this.layer);
|
||||
}
|
||||
|
||||
this.moving.delete(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关门
|
||||
* @param block 图块信息
|
||||
*/
|
||||
async closeDoor(block: Block) {
|
||||
const renderable = this.getRenderable(block);
|
||||
if (!renderable) return Promise.reject();
|
||||
const { renderable: data, count: frame, perTime } = renderable;
|
||||
data.animate = frame - 1;
|
||||
this.moving.add(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
|
||||
let now = 0;
|
||||
while (now >= 0) {
|
||||
await sleep(perTime);
|
||||
data.animate = --now;
|
||||
this.layer.update(this.layer);
|
||||
}
|
||||
this.moving.delete(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
awake(layer: Layer) {
|
||||
this.layer = layer;
|
||||
doorAdapter.add(this);
|
||||
}
|
||||
|
||||
onMovingUpdate(_layer: Layer, renderable: LayerMovingRenderable[]): void {
|
||||
renderable.push(...this.moving);
|
||||
}
|
||||
|
||||
onDestroy(_layer: Layer): void {
|
||||
doorAdapter.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
const doorAdapter = new RenderAdapter<LayerDoorAnimate>('door-animate');
|
||||
doorAdapter.receive('openDoor', (item, block: Block) => {
|
||||
return item.openDoor(block);
|
||||
});
|
||||
doorAdapter.receive('closeDoor', (item, block: Block) => {
|
||||
return item.closeDoor(block);
|
||||
});
|
||||
@@ -2,7 +2,6 @@ export * from './animate';
|
||||
export * from './block';
|
||||
export * from './cache';
|
||||
export * from './camera';
|
||||
export * from './floor';
|
||||
export * from './frame';
|
||||
export * from './graphics';
|
||||
export * from './hero';
|
||||
|
||||
@@ -8,11 +8,11 @@ import {
|
||||
RenderAdapter
|
||||
} from '@motajs/render-core';
|
||||
import { logger } from '@motajs/common';
|
||||
import { TimingFn } from 'mutate-animate';
|
||||
import { sleep, TimingFn } from 'mutate-animate';
|
||||
import { RenderableData, texture } from './cache';
|
||||
import { BlockCacher, CanvasCacheItem, ICanvasCacheItem } from './block';
|
||||
import { LayerFloorBinder, LayerGroupFloorBinder } from './floor';
|
||||
import { IAnimateFrame, renderEmits } from './frame';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
|
||||
export interface ILayerGroupRenderExtends {
|
||||
/** 拓展的唯一标识符 */
|
||||
@@ -1550,3 +1550,406 @@ export class Layer extends Container<ELayerEvent> {
|
||||
}
|
||||
|
||||
const layerAdapter = new RenderAdapter<Layer>('layer');
|
||||
|
||||
const { hook } = Mota.require('@user/data-base');
|
||||
|
||||
hook.on('setBlock', (x, y, floor, block) => {
|
||||
const isNow = floor === core.status.floorId;
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (floor === v.floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock('event', block, x, y);
|
||||
}
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.layer.layer === 'event') {
|
||||
if (v.floor === floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(block, x, y);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
hook.on('changingFloor', floor => {
|
||||
// 潜在隐患:如果putRenderData改成异步,那么会变成两帧后才能真正刷新并渲染
|
||||
// 考虑到楼层转换一般不会同时执行很多次,因此这里改为立刻更新
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (v.bindThisFloor) v.updateBindData();
|
||||
v.emit('floorChange', floor);
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.bindThisFloor) v.updateBindData();
|
||||
});
|
||||
});
|
||||
hook.on('setBgFgBlock', (name, number, x, y, floor) => {
|
||||
const isNow = floor === core.status.floorId;
|
||||
LayerGroupFloorBinder.activedBinder.forEach(v => {
|
||||
if (floor === v.floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(name, number, x, y);
|
||||
}
|
||||
});
|
||||
LayerFloorBinder.listenedBinder.forEach(v => {
|
||||
if (v.layer.layer === name) {
|
||||
if (v.floor === floor || (isNow && v.bindThisFloor)) {
|
||||
v.setBlock(number, x, y);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface LayerGroupBinderEvent {
|
||||
update: [floor: FloorIds];
|
||||
setBlock: [x: number, y: number, floor: FloorIds, block: AllNumbers];
|
||||
floorChange: [floor: FloorIds];
|
||||
}
|
||||
|
||||
/**
|
||||
* 楼层绑定拓展,用于LayerGroup,将楼层数据传输到渲染系统。
|
||||
* 添加后,会自动在LayerGroup包含的子Layer上添加LayerFloorBinder拓展,用于后续处理。
|
||||
* 当移除这个拓展时,其附属的所有子拓展也会一并被移除。
|
||||
*/
|
||||
export class LayerGroupFloorBinder
|
||||
extends EventEmitter<LayerGroupBinderEvent>
|
||||
implements ILayerGroupRenderExtends
|
||||
{
|
||||
id: string = 'floor-binder';
|
||||
|
||||
bindThisFloor: boolean = true;
|
||||
floor?: FloorIds;
|
||||
group!: LayerGroup;
|
||||
|
||||
/** 附属的子LayerFloorBinder拓展 */
|
||||
layerBinders: Set<LayerFloorBinder> = new Set();
|
||||
|
||||
private needUpdate: boolean = false;
|
||||
|
||||
static activedBinder: Set<LayerGroupFloorBinder> = new Set();
|
||||
|
||||
/**
|
||||
* 绑定楼层为当前楼层,并跟随变化
|
||||
*/
|
||||
bindThis() {
|
||||
this.floor = void 0;
|
||||
this.bindThisFloor = true;
|
||||
this.layerBinders.forEach(v => v.bindThis());
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为指定楼层
|
||||
* @param floorId 楼层id
|
||||
*/
|
||||
bindFloor(floorId: FloorIds) {
|
||||
this.bindThisFloor = false;
|
||||
this.floor = floorId;
|
||||
this.layerBinders.forEach(v => v.bindFloor(floorId));
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在下一帧进行绑定数据更新
|
||||
*/
|
||||
updateBind() {
|
||||
if (this.needUpdate || !this.group) return;
|
||||
this.needUpdate = true;
|
||||
this.group.requestBeforeFrame(() => {
|
||||
this.needUpdate = false;
|
||||
this.updateBindData();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 立刻进行数据绑定更新
|
||||
*/
|
||||
updateBindData() {
|
||||
this.layerBinders.forEach(v => {
|
||||
v.updateBindData();
|
||||
});
|
||||
|
||||
const floor = this.getFloor();
|
||||
this.emit('update', floor);
|
||||
}
|
||||
|
||||
getFloor() {
|
||||
return this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置图块
|
||||
*/
|
||||
setBlock(layer: FloorLayer, block: AllNumbers, x: number, y: number) {
|
||||
const ex = this.group
|
||||
.getLayer(layer)
|
||||
?.getExtends('floor-binder') as LayerFloorBinder;
|
||||
if (!ex) return;
|
||||
ex.setBlock(block, x, y);
|
||||
|
||||
const floor = this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
this.emit('setBlock', x, y, floor, block);
|
||||
}
|
||||
|
||||
checkLayerExtends(layer: Layer) {
|
||||
const ex = layer.getExtends('floor-binder');
|
||||
|
||||
if (!ex) {
|
||||
const extend = new LayerFloorBinder(this);
|
||||
layer.extends(extend);
|
||||
this.layerBinders.add(extend);
|
||||
} else {
|
||||
if (ex instanceof LayerFloorBinder) {
|
||||
ex.setParent(this);
|
||||
this.layerBinders.add(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
awake(group: LayerGroup) {
|
||||
this.group = group;
|
||||
|
||||
for (const layer of group.layers.values()) {
|
||||
this.checkLayerExtends(layer);
|
||||
}
|
||||
LayerGroupFloorBinder.activedBinder.add(this);
|
||||
}
|
||||
|
||||
onLayerAdd(_group: LayerGroup, layer: Layer): void {
|
||||
this.checkLayerExtends(layer);
|
||||
}
|
||||
|
||||
onDestroy(group: LayerGroup) {
|
||||
LayerGroupFloorBinder.activedBinder.delete(this);
|
||||
group.layers.forEach(v => {
|
||||
v.removeExtends('floor-binder');
|
||||
});
|
||||
this.removeAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 楼层绑定拓展,用于Layer的楼层渲染。
|
||||
* 注意,如果目标Layer是LayerGroup的子元素,那么会自动检测父元素是否包含LayerGroupFloorBinder拓展,
|
||||
* 如果包含,那么会自动将此拓展附加至父元素的拓展。当父元素的拓展被移除时,此拓展也会一并被移除。
|
||||
*/
|
||||
export class LayerFloorBinder implements ILayerRenderExtends {
|
||||
id: string = 'floor-binder';
|
||||
|
||||
parent?: LayerGroupFloorBinder;
|
||||
layer!: Layer;
|
||||
bindThisFloor: boolean = true;
|
||||
floor?: FloorIds;
|
||||
|
||||
static listenedBinder: Set<LayerFloorBinder> = new Set();
|
||||
|
||||
private needUpdate: boolean = false;
|
||||
|
||||
constructor(parent?: LayerGroupFloorBinder) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为当前楼层,并跟随变化
|
||||
*/
|
||||
bindThis() {
|
||||
this.floor = void 0;
|
||||
this.bindThisFloor = true;
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定楼层为指定楼层
|
||||
* @param floorId 楼层id
|
||||
*/
|
||||
bindFloor(floorId: FloorIds) {
|
||||
this.bindThisFloor = false;
|
||||
this.floor = floorId;
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
getFloor() {
|
||||
return this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置这个拓展附属至的父拓展(LayerGroupFloorBinder拓展)
|
||||
* @param parent 父拓展
|
||||
*/
|
||||
setParent(parent?: LayerGroupFloorBinder) {
|
||||
this.parent = parent;
|
||||
this.checkListen();
|
||||
}
|
||||
|
||||
private checkListen() {
|
||||
if (this.parent) LayerFloorBinder.listenedBinder.delete(this);
|
||||
else LayerFloorBinder.listenedBinder.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在下一帧进行绑定数据更新
|
||||
*/
|
||||
updateBind() {
|
||||
if (this.needUpdate) return;
|
||||
this.needUpdate = true;
|
||||
this.layer.requestBeforeFrame(() => {
|
||||
this.needUpdate = false;
|
||||
this.updateBindData();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置图块
|
||||
*/
|
||||
setBlock(block: AllNumbers, x: number, y: number) {
|
||||
this.layer.putRenderData([block], 1, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* 立刻更新绑定数据,而非下一帧
|
||||
*/
|
||||
updateBindData() {
|
||||
const floor = this.getFloor();
|
||||
if (!floor) return;
|
||||
core.extractBlocks(floor);
|
||||
const map = core.status.maps[floor];
|
||||
this.layer.setMapSize(map.width, map.height);
|
||||
const image = core.status.maps[this.getFloor()].images;
|
||||
if (this.layer.layer === 'event') {
|
||||
const m = map.map;
|
||||
this.layer.putRenderData(m.flat(), map.width, 0, 0);
|
||||
} else {
|
||||
const m = core.maps._getBgFgMapArray(this.layer.layer!, floor);
|
||||
this.layer.putRenderData(m.flat(), map.width, 0, 0);
|
||||
}
|
||||
if (this.layer.layer === 'bg') {
|
||||
// 别忘了背景图块
|
||||
this.layer.setBackground(texture.idNumberMap[map.defaultGround]);
|
||||
}
|
||||
const toDraw = image?.filter(v => v.canvas === this.layer.layer);
|
||||
this.layer.setFloorImage(toDraw ?? []);
|
||||
}
|
||||
|
||||
awake(layer: Layer) {
|
||||
this.layer = layer;
|
||||
if (!this.parent) {
|
||||
const group = layer.parent;
|
||||
if (group instanceof LayerGroup) {
|
||||
const ex = group.getExtends('floor-binder');
|
||||
if (ex instanceof LayerGroupFloorBinder) {
|
||||
ex.checkLayerExtends(layer);
|
||||
this.parent = ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkListen();
|
||||
}
|
||||
|
||||
onDestroy(_layer: Layer) {
|
||||
LayerFloorBinder.listenedBinder.delete(this);
|
||||
this.parent?.layerBinders.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
interface DoorAnimateRenderable {
|
||||
renderable: LayerMovingRenderable;
|
||||
count: number;
|
||||
perTime: number;
|
||||
}
|
||||
|
||||
export class LayerDoorAnimate implements ILayerRenderExtends {
|
||||
id: string = 'door-animate';
|
||||
|
||||
layer!: Layer;
|
||||
|
||||
private moving: Set<LayerMovingRenderable> = new Set();
|
||||
|
||||
private getRenderable(block: Block): DoorAnimateRenderable | null {
|
||||
const { x, y, id } = block;
|
||||
const renderable = texture.getRenderable(id);
|
||||
if (!renderable) return null;
|
||||
const image = renderable.autotile
|
||||
? renderable.image[0]
|
||||
: renderable.image;
|
||||
const time = block.event.doorInfo?.time ?? 160;
|
||||
const frame = renderable.render.length;
|
||||
const perTime = time / frame;
|
||||
|
||||
const data: LayerMovingRenderable = {
|
||||
x,
|
||||
y,
|
||||
zIndex: y,
|
||||
image,
|
||||
autotile: false,
|
||||
animate: 0,
|
||||
frame,
|
||||
bigImage: false,
|
||||
render: renderable.render,
|
||||
alpha: 1
|
||||
};
|
||||
return { renderable: data, count: frame, perTime };
|
||||
}
|
||||
|
||||
/**
|
||||
* 开门
|
||||
* @param block 图块信息
|
||||
*/
|
||||
async openDoor(block: Block) {
|
||||
const renderable = this.getRenderable(block);
|
||||
if (!renderable) return Promise.reject();
|
||||
const { renderable: data, count: frame, perTime } = renderable;
|
||||
data.animate = 0;
|
||||
this.moving.add(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
|
||||
let now = 0;
|
||||
while (now < frame) {
|
||||
await sleep(perTime);
|
||||
data.animate = ++now;
|
||||
this.layer.update(this.layer);
|
||||
}
|
||||
|
||||
this.moving.delete(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关门
|
||||
* @param block 图块信息
|
||||
*/
|
||||
async closeDoor(block: Block) {
|
||||
const renderable = this.getRenderable(block);
|
||||
if (!renderable) return Promise.reject();
|
||||
const { renderable: data, count: frame, perTime } = renderable;
|
||||
data.animate = frame - 1;
|
||||
this.moving.add(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
|
||||
let now = 0;
|
||||
while (now >= 0) {
|
||||
await sleep(perTime);
|
||||
data.animate = --now;
|
||||
this.layer.update(this.layer);
|
||||
}
|
||||
this.moving.delete(data);
|
||||
this.layer.requestUpdateMoving();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
awake(layer: Layer) {
|
||||
this.layer = layer;
|
||||
doorAdapter.add(this);
|
||||
}
|
||||
|
||||
onMovingUpdate(_layer: Layer, renderable: LayerMovingRenderable[]): void {
|
||||
renderable.push(...this.moving);
|
||||
}
|
||||
|
||||
onDestroy(_layer: Layer): void {
|
||||
doorAdapter.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
const doorAdapter = new RenderAdapter<LayerDoorAnimate>('door-animate');
|
||||
doorAdapter.receive('openDoor', (item, block: Block) => {
|
||||
return item.openDoor(block);
|
||||
});
|
||||
doorAdapter.receive('closeDoor', (item, block: Block) => {
|
||||
return item.closeDoor(block);
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { RenderAdapter } from '@motajs/render-core';
|
||||
import { HeroRenderer } from './hero';
|
||||
import { ILayerGroupRenderExtends, LayerGroup } from './layer';
|
||||
import { LayerGroupFloorBinder } from './floor';
|
||||
import { LayerGroupFloorBinder } from './layer';
|
||||
import { hyper, TimingFn } from 'mutate-animate';
|
||||
|
||||
export class FloorViewport implements ILayerGroupRenderExtends {
|
||||
|
||||
Reference in new issue
Block a user