feat: author first playable mystery

This commit is contained in:
2026-08-14 15:02:00 +02:00
parent d46a425401
commit b284275e98
13 changed files with 413 additions and 11 deletions
+23
View File
@@ -16,6 +16,29 @@ export function moveBoardPoint(origin: { x: number; y: number }, screenDelta: {
return { x: origin.x + screenDelta.x / zoom, y: origin.y + screenDelta.y / zoom }
}
export function nextOpenBoardPosition(
evidence: Pick<Evidence, 'x' | 'y' | 'width'>[],
preferred: { x: number; y: number },
size: { width: number; height?: number },
bounds = { width: 2400, height: 1500 },
) {
const height = size.height || 160
const gap = 28
const overlaps = (x: number, y: number) => evidence.some(item =>
x < item.x + item.width + gap && x + size.width + gap > item.x &&
y < item.y + 160 + gap && y + height + gap > item.y)
const xStep = size.width + 46
const yStep = height + 46
for (let row = 0; row < 7; row += 1) {
for (const column of [0, 1, -1, 2, -2, 3, -3]) {
const x = Math.max(80, Math.min(bounds.width - size.width - 80, preferred.x + column * xStep))
const y = Math.max(100, Math.min(bounds.height - height - 80, preferred.y + row * yStep))
if (!overlaps(x, y)) return { x, y }
}
}
return { x: Math.max(80, Math.min(bounds.width - size.width - 80, preferred.x)), y: Math.min(bounds.height - height - 80, preferred.y + evidence.length * 24) }
}
export function panViewport(origin: Viewport, screenDelta: { x: number; y: number }): Viewport {
return { ...origin, x: origin.x + screenDelta.x, y: origin.y + screenDelta.y }
}