# MyGamePlayable — контекст проєкту > Цей файл автоматично підвантажується в кожній сесії Claude Code. Тримай його > в актуальному стані: онови статуси, коли щось зміниться, видали "Day 5" секцію > коли вона остаточно перевірена і стабільна, додай нову секцію під наступний день. ## Стек і структура - **Не Babylon.js** — це **three.js** (`three@0.185`) обгорнутий у пропрієтарний SDK `@hitplay/playable_template` (плейбл-реклама, HitPlay). - Фізика: `cannon-es@0.20` + `cannon-es-debugger`. World піднятий через SDK (`Physics_internal.init(...)` в `src/templateConfig/beforeResourcesLoadedCb.ts:27`), дебаг-рендер тригериться прапорцем `Template.initConfig({ debug: { physics: false } })` в `src/index.ts` (поки `false` — увімкнути під час дебагу фізики). **SDK сам кличе `world.fixedStep()` кожен кадр** (`Physics_internal.update`, всередині пакету) — свій `world.step()`/`fixedStep()` НЕ викликати, це вже фіксований таймстеп з коробки. - `UpdateController.Instance.onUpdate` — єдиний update-event, `delta` в секундах (з `THREE.Clock.getDelta()`), без фіксованого таймстепу на цьому рівні (фіксований степ — тільки всередині cannon, через `fixedStep()`). - `ThreeC.removeFromScene(obj)` існує (просто `obj.removeFromParent()`) — використовувати для видалення спавнених/знищених мешів. ### Файли ``` src/controllers/ PlayerC.ts - джойстик-рух (nipplejs), AABB-колізії з "colliders", бій: неперервний AoE-swing по всіх breakable-цілях в зоні ураження (240°-конус, FACING_DOT_THRESHOLD=-0.5, Day 7 — див. "Кут ураження"), перебивається рухом TestSceneC.ts - завантажує ZombiePunk_Map.glb, /collider/i -> hidden+colliders, ставить cannon Wall-тіла на все, крім Lootable-крейтів; ініціалізує всі VFX/HUD-контролери (PropVfxC, SparkleFxC, WeaponTrailC, HudC) в правильному порядку CameraFollowC.ts - камера-слідкувач, obstacle-avoidance через Raycaster по тому ж масиву colliders (НЕ торкались) PhysicsC.ts - PhysicsLayer enum, PhysicsBody (Box/Sphere+cannon Body з коректним world-space size/rotation), PhysicsObjPair BreakablePropC.ts - парсить групу "Lootable" в мапі, S1/S2/S3 damage-stages, 2 хіти на стейдж, hit() advance stage / повне знищення (tween-джус, Day 6), дропає ресурси WeaponTrailC.ts - Day 7: hand-rolled screen-facing ribbon-шлейф за битою під час замаху (samples PlayerC.getWeaponAnchor(), обчислює "кінець бити" з реальної local bbox, не вгадує offset), тає/звужується за час, не тон-мап, toggled через PlayerC.updateCombat (isAttacking) ResourceC.ts - Day 7: спавн ресурсу з крейта -> scatter -> 2 баунси (відчутні, БЕЗ ротейту) -> на 2-му баунсі: білий флеш (окремий additive-оверлей-меш, БЕЗ squash-and-widen — чистий uniform shrink, тримається, не пружинить назад) + SparkleFxC-вибух зірочок -> staggered (по черзі, не купою) політ до HudC.getWorldAnchorPosition() (ціль пере-семплюється ЩОКАДРУ, не застигає, якщо камера рухається) з компенсацією перспективи (див. RESOURCE_ICON_BASE_SCALE, нижче) -> яскравіє й зникає рівно на іконці. НЕ знає про Pay Zone/гравця; візуал — клон реального "UI_Wood" з мапи; createVisual() — публічний доступ до цього візуалу (без баунс/флеш начинки) для інших контролерів (PayZoneC) PayZoneC.ts - Day 6/8: окремо зливає ResourceC.getCollectedCount() в Pay Zone (вузол мапи "UI_Interactive_Zone_02"), по одному ресурсу, тільки поки гравець стоїть в зоні; зникає після RESOURCES_TO_CLOSE_ZONE доставлених (зараз 20); росте плаский fill-overlay квад по мірі заповнення; політ депозиту (HudC.getWorldAnchorPosition() -> Pay Zone) БЕЗ ротейту, з тією ж компенсацією перспективи й базовим розміром, що й ResourceC (RESOURCE_ICON_BASE_SCALE, спільна константа — інакше токен виглядає більшим за ресурс, що щойно був на тому ж місці), плюс окремий DEPOSIT_FLIGHT_SCALE_MULTIPLIER для локального тюнінгу HudC.ts - Day 8: лічильник ресурсу — реальний дизайнерський ассет (resourceCounterBgSrc, Tool_15.webp з temp/, планка вже вбудована в картинку, не окрема іконка), DOM-оверлей в #ui, стилі в src/css/ui.css (не inline