import { logger } from '@motajs/common'; import { MotaOffscreenCanvas2D } from '@motajs/render'; import { mainSetting } from '@motajs/legacy-ui'; import { Sprite, Transform } from '@motajs/render'; import { gameListener, hook } from '@user/data-base'; import { ILayerGroupRenderExtends, LayerGroup, LayerGroupFloorBinder } from '../elements'; export class LayerGroupHalo implements ILayerGroupRenderExtends { id: string = 'halo'; group!: LayerGroup; binder!: LayerGroupFloorBinder; halo!: Halo; static sprites: Set = new Set(); awake(group: LayerGroup): void { this.group = group; const ex = group.getExtends('floor-binder'); if (ex instanceof LayerGroupFloorBinder) { this.binder = ex; this.halo = new Halo(); this.halo.setHD(true); this.halo.size(group.width, group.height); this.halo.setZIndex(75); this.halo.binder = ex; group.appendChild(this.halo); LayerGroupHalo.sprites.add(this.halo); } else { logger.error(1401); group.removeExtends('halo'); } } onDestroy(_group: LayerGroup): void { this.halo?.destroy(); LayerGroupHalo.sprites.delete(this.halo); } } const haloColor: Record = { 21: ['cyan'], 25: ['purple'], 26: ['blue'], 27: ['red'], 31: ['#3CFF49'], 29: ['#51E9FF'], 32: ['#fff966'] }; class Halo extends Sprite { /** 单元格大小 */ cellSize: number = 32; /** 当前楼层,用于获取有哪些光环 */ binder!: LayerGroupFloorBinder; constructor() { super('static', true); this.setRenderFn((canvas, transform) => { this.drawHalo(canvas, transform); }); } drawHalo(canvas: MotaOffscreenCanvas2D, _transform: Transform) { if (!mainSetting.getValue('screen.halo', true)) return; const floorId = this.binder.getFloor(); if (!floorId) return; const col = core.status.maps[floorId].enemy; if (!col) return; const [dx, dy] = col.translation; const list = col.haloList.concat( Object.keys(flags[`melt_${floorId}`] ?? {}).map(v => { const [x, y] = v.split(',').map(v => parseInt(v)); return { type: 'square', data: { x: x + dx, y: y + dy, d: 3 }, special: 25 }; }) ); const { ctx } = canvas; const cell = this.cellSize; ctx.lineWidth = 1; for (const halo of list) { if (halo.type === 'square') { const { x, y, d } = halo.data; let [color, border] = haloColor[halo.special]; let alpha = 0.1; let borderAlpha = 0.6; const { mouseX, mouseY } = gameListener; if (mouseX === halo.from?.x && mouseY === halo.from?.y) { alpha = 0.3; borderAlpha = 0.8; color = '#ff0'; border = '#ff0'; } const r = Math.floor(d / 2); const left = x - r; const top = y - r; ctx.fillStyle = color; ctx.strokeStyle = border ?? color; ctx.globalAlpha = alpha; ctx.fillRect(left * cell, top * cell, d * cell, d * cell); ctx.globalAlpha = borderAlpha; ctx.strokeRect(left * cell, top * cell, d * cell, d * cell); } } } } function updateHalo(block: Block) { if (block.event.cls === 'enemys' || block.event.cls === 'enemy48') { LayerGroupHalo.sprites.forEach(v => { const floor = v.binder.getFloor(); if (floor === core.status.floorId) { v.update(); } }); } } hook.on('enemyExtract', col => { LayerGroupHalo.sprites.forEach(v => { const floor = v.binder.getFloor(); if (col.floorId === floor) { v.update(); } }); }); gameListener.on('hoverBlock', updateHalo); gameListener.on('leaveBlock', updateHalo);