import { FLOOR, W as LW } from "../scene.ts"; import * as Wd from "../world.ts"; import { animate } from "./animation.ts"; import { pushLine, wantTurn } from "./conversation.ts"; import { logToday } from "./simulation.ts"; import { save } from "./storage.ts"; import { emit, store, view } from "./store.ts"; import { clamp } from "./utils.ts"; // ---------- catch minigame (after the pet said yes) ---------- export function startGame() { if (!store.tabOwned || !store.state.pet || store.state.asleep || view.game) return; view.game = { stars: [], score: 0, timeLeft: 20, last: performance.now(), spawn: 0, dir: 0, held: new Map(), }; view.target = view.x; emit(); } export function gameControl(id: string, dir: number) { const g = view.game; if (!g) return; g.held.delete(id); if (dir) g.held.set(id, dir); // The newest held input wins; releasing another finger/key cannot stop it. g.dir = [...g.held.values()].at(-1) || 0; view.target = view.x; } export function stopGameControls() { if (!view.game) return; view.game.held.clear(); view.game.dir = 0; view.target = view.x; } export function stepGame(now: number) { const g = view.game!; const dt = Math.min(0.05, (now - g.last) / 1000); g.last = now; g.timeLeft -= dt; g.spawn -= dt; if (g.spawn <= 0) { g.stars.push({ x: 8 + Math.random() * (LW - 16), y: -4, v: 18 + Math.random() * 14 + (20 - g.timeLeft), bad: Math.random() < 0.18, }); g.spawn = 0.55 + Math.random() * 0.5; } if (g.dir) view.target = clamp(view.x + g.dir * 70 * dt, 10, LW - 10); const dx = view.target - view.x; if (dx) { view.facing = Math.sign(dx); view.x += Math.sign(dx) * Math.min(Math.abs(dx), 70 * dt); view.walking = true; } else view.walking = false; for (const s of g.stars) { s.y += s.v * dt; if (!s.done && s.y > FLOOR - 16 && s.y < FLOOR - 4 && Math.abs(s.x - view.x) < 10) { s.done = true; if (s.bad) { g.score = Math.max(0, g.score - 1); animate("wow", 400, true); } else { g.score++; animate("happy", 400, true); } } } g.stars = g.stars.filter((s) => !s.done && s.y < FLOOR + 4); if (g.timeLeft <= 0) endGame(); } export function endGame() { const n = view.game!.score; view.game = null; view.target = view.x; emit(); store.state.stats.fun = clamp(store.state.stats.fun + 8 + n * 3); store.state.stats.energy = clamp(store.state.stats.energy - 8); store.state.counts.games++; pushLine(Wd.events.caught(store.state.owner, store.state.pet!.name, n)); logToday(`played catch (${n} ${n === 1 ? "star" : "stars"})`); save(); emit(); wantTurn(); }