feat: v0.3.0 — flat 2D camera: remove zoom-driven tilt + terrain; max zoom ~100 km screen width

This commit is contained in:
2026-09-17 00:33:10 +00:00
parent 11619d11b2
commit b7796e5d78
7 changed files with 15 additions and 80 deletions
-33
View File
@@ -1,33 +0,0 @@
import { describe, expect, it } from 'vitest';
import { pitchForZoom, smoothstep, PITCH_ZOOM_MIN, PITCH_ZOOM_MAX, MAX_PITCH_DEG } from './camera';
describe('smoothstep', () => {
it('clamps outside the edges and is 0.5 at the midpoint', () => {
expect(smoothstep(0, 1, -5)).toBe(0);
expect(smoothstep(0, 1, 2)).toBe(1);
expect(smoothstep(0, 1, 0.5)).toBeCloseTo(0.5);
});
});
describe('pitchForZoom', () => {
it('is 0 at and below the lower zoom threshold', () => {
expect(pitchForZoom(PITCH_ZOOM_MIN)).toBe(0);
expect(pitchForZoom(4)).toBe(0);
expect(pitchForZoom(0)).toBe(0);
});
it('is max pitch at and above the upper zoom threshold', () => {
expect(pitchForZoom(PITCH_ZOOM_MAX)).toBe(MAX_PITCH_DEG);
expect(pitchForZoom(15)).toBe(MAX_PITCH_DEG);
});
it('rises smoothly between thresholds (monotonic, midpoint = half max)', () => {
expect(pitchForZoom((PITCH_ZOOM_MIN + PITCH_ZOOM_MAX) / 2)).toBeCloseTo(MAX_PITCH_DEG / 2);
let prev = -1;
for (let z = PITCH_ZOOM_MIN; z <= PITCH_ZOOM_MAX; z += 0.25) {
const p = pitchForZoom(z);
expect(p).toBeGreaterThan(prev);
prev = p;
}
});
});
-13
View File
@@ -1,13 +0,0 @@
export const PITCH_ZOOM_MIN = 6;
export const PITCH_ZOOM_MAX = 12;
export const MAX_PITCH_DEG = 45;
export function smoothstep(edge0: number, edge1: number, x: number): number {
const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));
return t * t * (3 - 2 * t);
}
// Pitch is a pure function of zoom so it never fights user pan/zoom gestures.
export function pitchForZoom(zoom: number): number {
return smoothstep(PITCH_ZOOM_MIN, PITCH_ZOOM_MAX, zoom) * MAX_PITCH_DEG;
}