Files
DndGamePlayer/app/shared/effectEraserHitTest.test.ts
T
Ivan Fontosh 20c838da7d feat(effects): вода, облако яда, луч света; пульт и окна демонстрации
- Поле: вода (сплошная заливка по штриху, превью кистью), туман/огонь/дождь без изменений логики.

- Действия: облако яда (частицы, круглая текстура, звук oblako-yada.mp3, длительность как у трека), луч света и заморозка со звуками из public/.

- Пульт: инструменты воды и яда, синхрон SFX, тесты панели и ластика.

- Окно управления: дочернее от окна просмотра (Z-order).

- Типы эффектов, effectsStore prune, hit-test ластика.

Made-with: Cursor
2026-04-20 11:03:57 +08:00

84 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict';
import test from 'node:test';
import { minDistSqEffectToPoint, pickEraseTargetId } from './effectEraserHitTest';
import type { EffectInstance } from './types/effects';
const base = { seed: 1, createdAtMs: 0 };
void test('pickEraseTargetId: fire/rain по штриху как туман', () => {
const fire: EffectInstance = {
...base,
id: 'f1',
type: 'fire',
points: [{ x: 0.5, y: 0.5, tMs: 0 }],
radiusN: 0.05,
opacity: 1,
lifetimeMs: null,
};
const id = pickEraseTargetId([fire], { x: 0.51, y: 0.5 }, 0.05);
assert.equal(id, 'f1');
});
void test('pickEraseTargetId: вода по штриху как туман', () => {
const water: EffectInstance = {
...base,
id: 'w1',
type: 'water',
points: [{ x: 0.4, y: 0.55, tMs: 0 }],
radiusN: 0.06,
opacity: 0.5,
lifetimeMs: null,
};
const id = pickEraseTargetId([water], { x: 0.41, y: 0.55 }, 0.05);
assert.equal(id, 'w1');
});
void test('minDistSqEffectToPoint: молния — расстояние до отрезка', () => {
const bolt: EffectInstance = {
...base,
id: 'L1',
type: 'lightning',
start: { x: 0, y: 0 },
end: { x: 1, y: 0 },
widthN: 0.02,
intensity: 1,
lifetimeMs: 500,
};
const mid = minDistSqEffectToPoint(bolt, { x: 0.5, y: 0.1 });
assert.ok(Math.abs(mid - 0.01) < 1e-9);
const end = minDistSqEffectToPoint(bolt, { x: 1, y: 0 });
assert.equal(end, 0);
});
void test('minDistSqEffectToPoint: луч света — как у молнии, отрезок', () => {
const beam: EffectInstance = {
...base,
id: 'S1',
type: 'sunbeam',
start: { x: 0.5, y: 0 },
end: { x: 0.5, y: 0.8 },
widthN: 0.04,
intensity: 1,
lifetimeMs: 220,
};
const onBeam = minDistSqEffectToPoint(beam, { x: 0.5, y: 0.4 });
assert.equal(onBeam, 0);
const aside = minDistSqEffectToPoint(beam, { x: 0.52, y: 0.4 });
assert.ok(aside > 0 && aside < 0.01);
});
void test('pickEraseTargetId: scorch с учётом inst.radiusN', () => {
const sc: EffectInstance = {
...base,
id: 's1',
type: 'scorch',
at: { x: 0.5, y: 0.5 },
radiusN: 0.08,
opacity: 1,
lifetimeMs: 1000,
};
const id = pickEraseTargetId([sc], { x: 0.59, y: 0.5 }, 0.02);
assert.equal(id, 's1');
});