/**
* Окно частиц (общее для пепла и мотыльков): окно видимости движка,
* расширенное маржой за край кадра. В марже альфа частицы гаснет до нуля —
* заворачивание окна происходит уже за экраном, без «появления из воздуха»;
* у видимой границы частица полностью непрозрачна (перекрытие кадра).
*/
import type { VoxelRenderer } from '@rpg/engine';
/** Прямоугольное окно в мировых координатах (по x/z). */
export interface Window2 {
minX: number; maxX: number; minZ: number; maxZ: number;
}
/** Окно видимости слоя [y0,y1], расширенное маржой за край кадра. */
export function particleWindow(
renderer: VoxelRenderer, y0: number, y1: number, margin: number,
): Window2 {
const b = renderer.visibleWindow(y0, y1);
return { minX: b.minX - margin, maxX: b.maxX + margin, minZ: b.minZ - margin, maxZ: b.maxZ + margin };
}
/** Заворачивание значения в окно [min, min+size) — респавн с другой стороны. */
export function wrap(v: number, min: number, size: number): number {
let r = (v - min) % size;
if (r < 0) r += size;
return min + r;
}
/** Альфа у края окна: 0 в марже (за экраном), 1 внутри кадра. */
export function edgeAlpha(w: Window2, margin: number, x: number, z: number): number {
const d = Math.min(x - w.minX, w.maxX - x, z - w.minZ, w.maxZ - z);
return Math.max(0, Math.min(1, d / margin));
}