mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 20:59:37 +08:00
217 lines
6.1 KiB
TypeScript
217 lines
6.1 KiB
TypeScript
import { EmitableEvent, EventEmitter } from '../core/common/eventEmitter';
|
|
|
|
// ----- 加载事件
|
|
interface GameLoadEvent extends EmitableEvent {
|
|
coreLoaded: () => void;
|
|
autotileLoaded: () => void;
|
|
coreInit: () => void;
|
|
materialLoaded: () => void;
|
|
}
|
|
|
|
class GameLoading extends EventEmitter<GameLoadEvent> {
|
|
private autotileLoaded: number = 0;
|
|
private autotileNum?: number;
|
|
private autotileListened: boolean = false;
|
|
|
|
private materialsNum: number = main.materials.length;
|
|
private materialsLoaded: number = 0;
|
|
|
|
constructor() {
|
|
super();
|
|
this.on(
|
|
'coreInit',
|
|
() => {
|
|
this.autotileNum = Object.keys(
|
|
core.material.icons.autotile
|
|
).length;
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
this.on('materialLoaded', () => {
|
|
core.loader._loadMaterials_afterLoad();
|
|
});
|
|
}
|
|
|
|
addMaterialLoaded() {
|
|
this.materialsLoaded++;
|
|
if (this.materialsLoaded === this.materialsNum) {
|
|
this.emit('materialLoaded');
|
|
}
|
|
}
|
|
|
|
addAutotileLoaded() {
|
|
this.autotileLoaded++;
|
|
if (this.autotileLoaded === this.autotileNum) {
|
|
this.emit('autotileLoaded');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 当自动原件加载完毕时
|
|
* @param autotiles 自动原件数组
|
|
*/
|
|
onAutotileLoaded(
|
|
autotiles: Partial<Record<AllIdsOf<'autotile'>, HTMLImageElement>>
|
|
) {
|
|
if (this.autotileListened) return;
|
|
this.autotileListened = true;
|
|
this.on('autotileLoaded', () => {
|
|
const keys = Object.keys(
|
|
core.material.icons.autotile
|
|
) as AllIdsOf<'autotile'>[];
|
|
|
|
keys.forEach(v => {
|
|
core.material.images.autotile[v] = autotiles[v]!;
|
|
});
|
|
|
|
setTimeout(() => {
|
|
core.maps._makeAutotileEdges();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
export const loading = new GameLoading();
|
|
|
|
export interface GameEvent extends EmitableEvent {
|
|
/** Emitted in events.prototype.resetGame. */
|
|
reset: () => void;
|
|
/** Emitted in src/App.vue setup. */
|
|
mounted: () => void;
|
|
/** Emitted in plugin/ui.js */
|
|
statusBarUpdate: () => void;
|
|
/** Emitted in core/index.ts */
|
|
renderLoaded: () => void;
|
|
// /** Emitted in libs/events.js */
|
|
afterGetItem: (
|
|
itemId: AllIdsOf<'items'>,
|
|
x: number,
|
|
y: number,
|
|
isGentleClick: boolean
|
|
) => void;
|
|
afterOpenDoor: (doorId: AllIdsOf<'animates'>, x: number, y: number) => void;
|
|
afterChangeFloor: (floorId: FloorIds) => void;
|
|
}
|
|
|
|
export const hook = new EventEmitter<GameEvent>();
|
|
|
|
interface ListenerEvent extends EmitableEvent {
|
|
// block
|
|
hoverBlock: (block: Block, ev: MouseEvent) => void;
|
|
leaveBlock: (block: Block, ev: MouseEvent, leaveGame: boolean) => void;
|
|
clickBlock: (block: Block, ev: MouseEvent) => void;
|
|
// mouse
|
|
mouseMove: (ev: MouseEvent) => void;
|
|
}
|
|
|
|
class GameListener extends EventEmitter<ListenerEvent> {
|
|
static num: number = 0;
|
|
|
|
num: number = GameListener.num++;
|
|
|
|
constructor() {
|
|
super();
|
|
if (main.replayChecking) return;
|
|
if (!!window.core) {
|
|
this.init();
|
|
} else {
|
|
loading.once('coreInit', () => {
|
|
this.init();
|
|
});
|
|
}
|
|
}
|
|
|
|
private init() {
|
|
// ----- block
|
|
let lastHoverX = -1;
|
|
let lastHoverY = -1;
|
|
|
|
const data = core.canvas.data.canvas;
|
|
|
|
const getBlockLoc = (px: number, py: number, size: number) => {
|
|
return [
|
|
Math.floor(((px * 32) / size + core.bigmap.offsetX) / 32),
|
|
Math.floor(((py * 32) / size + core.bigmap.offsetY) / 32)
|
|
];
|
|
};
|
|
|
|
// hover & leave & mouseMove
|
|
data.addEventListener('mousemove', e => {
|
|
if (
|
|
core.status.lockControl ||
|
|
!core.isPlaying() ||
|
|
!core.status.floorId
|
|
)
|
|
return;
|
|
this.emit('mouseMove', e);
|
|
const {
|
|
x: px,
|
|
y: py,
|
|
size
|
|
} = core.actions._getClickLoc(e.clientX, e.clientY);
|
|
const [bx, by] = getBlockLoc(px, py, size);
|
|
const blocks = core.getMapBlocksObj();
|
|
if (lastHoverX !== bx || lastHoverY !== by) {
|
|
const lastBlock = blocks[`${lastHoverX},${lastHoverY}`];
|
|
const block = blocks[`${bx},${by}`];
|
|
if (!!lastBlock) {
|
|
this.emit('leaveBlock', lastBlock, e, false);
|
|
}
|
|
if (!!block) {
|
|
this.emit('hoverBlock', block, e);
|
|
lastHoverX = bx;
|
|
lastHoverY = by;
|
|
} else {
|
|
lastHoverX = -1;
|
|
lastHoverY = -1;
|
|
}
|
|
}
|
|
});
|
|
data.addEventListener('mouseleave', e => {
|
|
if (
|
|
core.status.lockControl ||
|
|
!core.isPlaying() ||
|
|
!core.status.floorId
|
|
)
|
|
return;
|
|
const blocks = core.getMapBlocksObj();
|
|
const lastBlock = blocks[`${lastHoverX},${lastHoverY}`];
|
|
if (!!lastBlock) {
|
|
this.emit('leaveBlock', lastBlock, e, true);
|
|
}
|
|
lastHoverX = -1;
|
|
lastHoverY = -1;
|
|
});
|
|
// click
|
|
data.addEventListener('click', e => {
|
|
if (
|
|
core.status.lockControl ||
|
|
!core.isPlaying() ||
|
|
!core.status.floorId
|
|
)
|
|
return;
|
|
const {
|
|
x: px,
|
|
y: py,
|
|
size
|
|
} = core.actions._getClickLoc(e.clientX, e.clientY);
|
|
const [bx, by] = getBlockLoc(px, py, size);
|
|
const blocks = core.getMapBlocksObj();
|
|
const block = blocks[`${bx},${by}`];
|
|
if (!!block) {
|
|
this.emit('clickBlock', block, e);
|
|
}
|
|
});
|
|
|
|
// ----- mouse
|
|
}
|
|
}
|
|
|
|
export const gameListener = new GameListener();
|
|
|
|
declare global {
|
|
interface Main {
|
|
loading: GameLoading;
|
|
}
|
|
}
|