1f4b5b70a4c6ccf57f1bc14fc054788714874b16
Codex post-fix review: v2 watchdog (velocity-based) НЕ разлеплял реальный матч — мяч застревал 90 секунд с ball_unstuck attempt:1 hadOverlap:false, но эскалация до hard_respawn не происходила. Причина: Matter имеет micro- velocity jitter при contact resolve, поэтому speed периодически превышал threshold → slow timer сбрасывался → fire не успевал. ## Решение: position-based detection Watchdog теперь принимает (position, now) вместо (speed, now): - Если за stuckDurationMs мяч физически не сдвинулся >= 30px → stuck - Healthy reset: 100 px за 2000ms → сбросить attempts - Position history с pruning (4s окно) - Эскалация: 3 nudge → 1 hard_respawn → clear history Это устойчиво к micro-jitter contact manifold — physical displacement не зависит от velocity samples. ## Integration smoke tests (codex #3) Два smoke-теста симулируют реальный gameplay сценарий: 1. «мяч застрял на bumper'е с micro-jitter ±0.3px → 10s симуляция → должно быть ≥3 nudge + ≥1 hard_respawn, всего events < 15 (rate-limit telemetry-noise)». Это ловит exactly баг с 20+ unstuck. 2. «launchBall с healthy движением (200 px/sec bouncing) → ноль false-fire'ов за 10s». Проверяет что watchdog не дёргает живой мяч. Эти тесты НЕ зависят от Phaser/Matter и валидируют core invariant. ## MatchScene wiring - watchdog.tick(this.ball.position, this.time.now) — position-only - findNearestOverlap searchRadius 60→80, tolerance 2→14 px (захватывает «почти-overlap» edge cases когда мяч слегка вылетел из contact zone) ## Tests 107/107 passed (было 102). 19 unit-тестов для watchdog (включая 2 smoke). Удалён CFG unused const. Поправлен non-null assertion warning. ## Trade-offs - Position-based нечувствителен к velocity вообще — для booster.aiming watchdog.reset() предотвращает false-fire (sticky-ball). - После hard_respawn watchdog clear полностью; первые 1.5s после respawn новый stuck не fire'тся (нет ещё истории). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pinball-Duel
Single-player пинбол vs 4 AI-личности (head-to-head формат, Williams Joust 1983).
Stack: Phaser 4 (beta) + TypeScript + Vite + Matter.js (bundled). Capacitor добавляется в Phase 1.5.
Platforms:
- MVP: Yandex Games (web only)
- Phase 1.5 (post-MVP-launch): Google Play + RuStore (Android, через Capacitor)
- Post-Phase 2: iOS (если PMF подтвердится)
Status: Phase 0 (pre-production) в процессе. Концепт-пакет — ~/Knowledge/Projects/pinball-duel/ (19 файлов, 10 audit-раундов).
Development
Requirements
- Node.js 20+
- npm
Setup
npm install
npm run dev # localhost:5173
Build & checks
npm run build # type-check + production build → dist/
npm run preview # serve build locally
npm run typecheck # tsc --noEmit
npm run lint # ESLint
npm run test # Vitest
Architecture
Game stack
- Phaser 4 — game engine + Matter.js physics (bundled)
- TypeScript strict — все типы из
src/types/index.ts(схемы из data-contracts.md) - Vite — bundler + dev server (с
base: './'для YG)
Platform Adapter
Game-код не знает о платформе через PlatformAdapter interface (src/platform/). Реализации:
MockPlatformAdapter— local dev и unit testsYgPlatformAdapter— Yandex Games SDK (MVP)CapacitorAdmobAdapter— Phase 1.5 (Play)RuStorePlatformAdapter— Phase 1.5 (RuStore)
Detection и factory в PlatformAdapter.ts::createPlatformAdapter().
Структура папок
src/
config/ Remote Config defaults, палитра, константы
types/ SaveState, MatchResult, RemoteConfig, etc.
platform/ PlatformAdapter interface + 4 реализации
scenes/ Phaser scenes (Boot, Preload, MainMenu, Setup, Match, Result)
game/ Game objects (Ball, Flipper, Bumper, Table, Match orchestration)
ai/ AI personalities (Defensive, Aggressive, Trickster, Ghost) + heuristics
scoring/ calculateScores + MatchTracker (defensive setup scoring + bumper points)
Фазовый план
| Phase | Содержание |
|---|---|
| 0 (✅) | Vite + Phaser 4 + TS boilerplate; Platform Adapter |
| 1 (✅) | Core mechanics: матч, флипперы, мяч, last-touch, fixed bumpers, Defensive Easy AI |
| 2 (✅) | Setup-фаза, 4 BumperType, 4 AI-личности × 3 сложности |
| 3 (✅ partial, sprint-mode) | Бустер «Захват» player-side, Hard difficulty (config-driven), cloud-save, 15 achievements. AI cradle + Ghost adaptation вынесены в backlog — см. KNOWN_ISSUES.md |
| 4 | Campaign + Tournament + визуальный polish (шейдеры), ассеты |
| 5 | YG SDK ads + payments + Remote Config |
| 6 | YG polish + submission + soft launch |
| 1.5 (post-MVP launch) | Capacitor: Google Play + RuStore mobile native |
Operational docs (в репо)
KNOWN_ISSUES.md— toolchain vulnerabilities, плановые апгрейды, текущие game-side caveatsplaytest-protocol.md— спека blind-attribution тестирования AI-личностей для закрытия Phase 2 DoD
Документация (концепт-пакет)
~/Knowledge/Projects/pinball-duel/ — 19 файлов:
index.md— overview + decision-history (10 audit-раундов)concepts/scope-lock.md— что в каждой фазе (single source of truth)concepts/data-contracts.md— все schema'ы (Remote Config, MatchResult, SaveState, leaderboard formula)concepts/definition-of-done.md— DoD per фазаconcepts/telemetry-spec.md— event mapconcepts/development-roadmap.md— план разработкиconcepts/monetization.md— IAP + Anti-A2W правилоconcepts/bot-ai-design.md— 4 AI-личностиplayer-guide.md— narrative-руководство игрока
License
Proprietary, all rights reserved.
Description
Single-player пинбол vs 4 AI-личности (head-to-head, Williams Joust 1983 format). Phaser 4 + TS + Vite + Matter.js. MVP YG-web only.
Languages
TypeScript
99.4%
HTML
0.6%