63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
applyRadialDeadzone,
|
|
cameraRelativeMovement,
|
|
cameraYawAfterHorizontalLook,
|
|
clampCameraPitch,
|
|
DEFAULT_CAMERA_PITCH,
|
|
normalizePlanar,
|
|
wrapAngle,
|
|
} from "./inputMath";
|
|
|
|
describe("input math", () => {
|
|
it("removes stick drift and remaps motion outside the deadzone", () => {
|
|
expect(applyRadialDeadzone(0.08, -0.05)).toEqual([0, 0]);
|
|
const [x, y] = applyRadialDeadzone(0.59, 0);
|
|
expect(x).toBeCloseTo(0.5, 2);
|
|
expect(y).toBe(0);
|
|
});
|
|
|
|
it("caps diagonal movement at unit length", () => {
|
|
const [x, z] = normalizePlanar(1, 1);
|
|
expect(Math.hypot(x, z)).toBeCloseTo(1);
|
|
});
|
|
|
|
it("rotates +Z-forward movement by camera yaw", () => {
|
|
expect(cameraRelativeMovement(0, 1, 0)).toEqual([0, 1]);
|
|
const [x, z] = cameraRelativeMovement(0, 1, -Math.PI / 2);
|
|
expect(x).toBeCloseTo(-1);
|
|
expect(z).toBeCloseTo(0);
|
|
});
|
|
|
|
it("maps positive lateral input to the rendered camera's screen-right direction", () => {
|
|
expect(cameraRelativeMovement(1, 0, 0)).toEqual([-1, 0]);
|
|
expect(cameraRelativeMovement(-1, 0, 0)).toEqual([1, 0]);
|
|
|
|
const yaw = 0.73;
|
|
const [worldX, worldZ] = cameraRelativeMovement(1, 0, yaw);
|
|
const screenRight = [-Math.cos(yaw), Math.sin(yaw)] as const;
|
|
expect(worldX * screenRight[0] + worldZ * screenRight[1]).toBeCloseTo(1);
|
|
});
|
|
|
|
it("turns toward screen-right for positive mouse or right-stick look", () => {
|
|
expect(cameraYawAfterHorizontalLook(0, 0.25)).toBeCloseTo(-0.25);
|
|
expect(cameraYawAfterHorizontalLook(0, -0.25)).toBeCloseTo(0.25);
|
|
expect(cameraYawAfterHorizontalLook(0.7, Number.NaN)).toBeCloseTo(0.7);
|
|
});
|
|
|
|
it("clamps pitch and wraps yaw", () => {
|
|
expect(clampCameraPitch(-3)).toBe(-0.18);
|
|
expect(clampCameraPitch(3)).toBe(0.88);
|
|
expect(wrapAngle(Math.PI * 3)).toBeCloseTo(Math.PI);
|
|
});
|
|
|
|
it("recovers from non-finite controller and camera values", () => {
|
|
expect(applyRadialDeadzone(Number.NaN, 0)).toEqual([0, 0]);
|
|
expect(normalizePlanar(Number.POSITIVE_INFINITY, 1)).toEqual([0, 0]);
|
|
expect(cameraRelativeMovement(0, 1, Number.NaN)).toEqual([0, 1]);
|
|
expect(cameraYawAfterHorizontalLook(Number.NaN, 1)).toBeCloseTo(-1);
|
|
expect(clampCameraPitch(Number.NaN)).toBe(DEFAULT_CAMERA_PITCH);
|
|
expect(wrapAngle(Number.NaN)).toBe(0);
|
|
});
|
|
});
|