From 4a0d1cb76da9fbe890f731192dea33fd4b53bc24 Mon Sep 17 00:00:00 2001 From: "goose.art" Date: Tue, 31 Mar 2026 13:25:26 -0700 Subject: [PATCH] =?UTF-8?q?fix=20flies:=20spawn=20from=20edges,=20clamp=20?= =?UTF-8?q?rotation=20to=20=C2=B130deg,=20flip=20when=20moving=20right?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/FlySpawner.svelte | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/lib/FlySpawner.svelte b/src/lib/FlySpawner.svelte index f8aab86..59e681e 100644 --- a/src/lib/FlySpawner.svelte +++ b/src/lib/FlySpawner.svelte @@ -17,6 +17,7 @@ targetX: number; // where it's heading (%) targetY: number; // where it's heading (%) rotation: number; // current rotation (deg) + flipped: boolean; // true when moving right (sprite faces left by default) splatted: boolean; // has it been clicked? fading: boolean; // is it fading out after splat? } @@ -26,8 +27,20 @@ let spawnTimer: ReturnType | null = null; let moveInterval: ReturnType | null = null; + /** Random position for fly targets — anywhere on screen */ function randomPercent() { - return Math.random() * 80 + 10; // 10–90% to stay away from edges + return Math.random() * 80 + 10; // 10–90% + } + + /** Spawn position — always from a screen edge */ + function edgeSpawnPosition(): { x: number; y: number } { + const edge = Math.floor(Math.random() * 4); + switch (edge) { + case 0: return { x: -5, y: Math.random() * 100 }; // left + case 1: return { x: 105, y: Math.random() * 100 }; // right + case 2: return { x: Math.random() * 100, y: -5 }; // top + default: return { x: Math.random() * 100, y: 105 }; // bottom + } } function spawnFly() { @@ -36,13 +49,15 @@ return; } + const spawn = edgeSpawnPosition(); const fly: Fly = { id: nextId++, - x: randomPercent(), - y: randomPercent(), + x: spawn.x, + y: spawn.y, targetX: randomPercent(), targetY: randomPercent(), - rotation: Math.random() * 360, + rotation: (Math.random() - 0.5) * 20, + flipped: false, splatted: false, fading: false, }; @@ -96,13 +111,22 @@ const speed = 0.4 + Math.random() * 0.3; const wobbleX = (Math.random() - 0.5) * 1.5; const wobbleY = (Math.random() - 0.5) * 1.5; + + // Sprite faces left by default, so 0° = moving left. + // Only rotate ±30° from the current heading to keep it level. const angle = Math.atan2(dy, dx) * (180 / Math.PI); + // Clamp to a gentle wobble: -30° to +30° from horizontal + const clampedAngle = Math.max(-30, Math.min(30, angle > 90 ? angle - 180 : angle < -90 ? angle + 180 : angle)); + + // Flip horizontally when moving right (sprite faces left by default) + const movingRight = dx > 0; return { ...f, x: f.x + (dx / dist) * speed + wobbleX, y: f.y + (dy / dist) * speed + wobbleY, - rotation: angle + (Math.random() - 0.5) * 30, + rotation: clampedAngle + (Math.random() - 0.5) * 10, + flipped: movingRight, }; }); } @@ -125,7 +149,7 @@ class="fly" class:splatted={fly.splatted} class:fading={fly.fading} - style="left: {fly.x}%; top: {fly.y}%; transform: rotate({fly.rotation}deg);" + style="left: {fly.x}%; top: {fly.y}%; transform: rotate({fly.rotation}deg) scaleX({fly.flipped ? -1 : 1});" onmousedown={() => splatFly(fly.id)} ontouchstart={() => splatFly(fly.id)} > -- 2.51.2