Newer
Older
rpg / packages / engine / src / anim / __tests__ / SpriteMotion.test.ts
import { describe, expect, it } from 'vitest';
import { SpriteMotion } from '../SpriteMotion';

/** Минимальный стенд под интерфейс Container, который трогает SpriteMotion. */
function fakeView(x = 10, y = 20) {
    const v = {
        x,
        y,
        rotation: 0,
        alpha: 1,
        scale: { _sx: 1, _sy: 1, set(sx: number, sy: number) { this._sx = sx; this._sy = sy; },
            get x() { return this._sx; }, get y() { return this._sy; } },
        destroyed: false
    };
    return v;
}

describe('SpriteMotion', () => {
    it('blink не трогает позицию: движущийся view сохраняет внешнее перемещение', () => {
        const v = fakeView(5, 7);
        const m = new SpriteMotion(v as never, { blink: { period: 0.25, duty: 1 } });
        v.x = 100; // извне (синк вью героя)
        v.y = 50;
        m.update(0.1);
        m.update(0.1);
        expect(v.x).toBe(100);
        expect(v.y).toBe(50);
    });

    it('bob смещает Y относительно базы, X держит; detach возвращает базу', () => {
        const v = fakeView(10, 20);
        const m = new SpriteMotion(v as never, { bob: { amplitude: 4, period: 1 } });
        m.update(0.25); // четверть периода — максимальное смещение
        expect(v.x).toBe(10);
        expect(v.y).not.toBe(20);
        m.detach();
        expect(v.x).toBe(10);
        expect(v.y).toBe(20);
    });

    it('pulse меняет alpha и scale, но не позицию', () => {
        const v = fakeView();
        const m = new SpriteMotion(v as never, { pulse: { min: 0.5, max: 1, period: 1 } });
        m.update(0.25);
        expect(v.alpha).not.toBe(1);
        expect(v.x).toBe(10);
        expect(v.y).toBe(20);
    });
});