/**
* Экранные слои атмосферы (v1 Atmosphere + движковая виньетка): виньетка
* опасности (края экрана темнеют — накат без полотна) и пелена наката.
* DOM-оверлеи поверх канваса: уровень плавно следует за целью (фейд, как
* v1 vignette.set / fog.alpha), детерминированно от ручного времени.
*/
/** Фейд уровней (сек) — v1 VIGNETTE_FADE. */
const FADE = 0.5;
/** Линейный подход к цели с ограничением шага. */
function approach(v: number, target: number, maxStep: number): number {
if (v < target) return Math.min(target, v + maxStep);
return Math.max(target, v - maxStep);
}
export class ScreenFx {
private vignette = 0;
private haze = 0;
constructor(
private readonly vignetteEl: HTMLElement,
private readonly hazeEl: HTMLElement,
) {}
/**
* Тик слоёв: виньетка 0..1 и пелена наката (alpha 0..1; v1: 0.12 с
* полотном, 0.28 без). В диалоге/катсцене не зовётся — уровни держатся.
*/
update(dt: number, vignetteTarget: number, hazeTarget: number): void {
const step = dt / FADE;
this.vignette = approach(this.vignette, vignetteTarget, step);
this.haze = approach(this.haze, hazeTarget, step);
this.vignetteEl.style.opacity = this.vignette.toFixed(3);
this.hazeEl.style.opacity = this.haze.toFixed(3);
}
/** Мгновенный сброс (смена области — старый накат не переезжает). */
reset(): void {
this.vignette = 0;
this.haze = 0;
this.vignetteEl.style.opacity = '0';
this.hazeEl.style.opacity = '0';
}
}