update cloud.md
This commit is contained in:
@@ -88,12 +88,39 @@ src/controllers/
|
||||
PropVfxC.ts - Day 6: завантажує дизайнерські quarks.art VFX-префаби
|
||||
(JSON з temp/, sparks/dust/debris) для хіту/знищення
|
||||
крейтів
|
||||
WeaponHudC.ts - Day 8: статична юайка внизу-зліва — восьмикутна
|
||||
плита (weaponHudBgSrc, ZombiePunk_Icon-Bottom.webp з
|
||||
temp/) + іконка бити (weaponIconBatSrc, Tool_2.webp)
|
||||
+ хардкоджений текст "LVL 0" (нема системи рівнів
|
||||
зброї в проєкті — суто візуал під референс). Іконка
|
||||
завжди бита, не стежить за поточною екіпірованою
|
||||
зброєю (pistol/bat) — окреме, свідомо не зроблене
|
||||
рішення
|
||||
ZombieInvasionHudC.ts - Day 8: топ-центр "ZOMBIE INVASION" — заголовок +
|
||||
таймер-бар. Голова зомбі (zombieHeadIconSrc,
|
||||
REF_1.png з temp/ — файл НАСПРАВДІ webp, не png,
|
||||
розширення в джерелі помилкове) їде з
|
||||
right:100% -> left:0% за TIMER_DURATION_S (120с)
|
||||
через CSS transition (JS лише раз перемикає
|
||||
значення); окремий .zombie-invasion__fill росте
|
||||
0%->100% width з right:0 в ТОЙ САМИЙ момент/тривалість
|
||||
— їх ліва межа завжди математично збігається з
|
||||
позицією голови, без пофреймової синхронізації.
|
||||
Останні WARNING_FRACTION=0.05 (6с) — pulse+червоний
|
||||
флеш через setTimeout+клас (CSS keyframes самі
|
||||
крутяться в infinite, ніхто їх не зупиняє після
|
||||
заповнення — свідомо, за проханням користувача).
|
||||
Немає дизайнерського ассету під сам бар/трек —
|
||||
чистий CSS pill, лише голова — реальна картинка
|
||||
ThreeC.ts/CameraC.ts - базовий сетап three.js/камери від SDK
|
||||
resources/meshes/ - ZombiePunk_Map.glb, ZombiePunk_Character.glb
|
||||
resources/images/ - resource_counter_bg.webp (Tool_15.webp з temp/,
|
||||
дизайнерський плейт лічильника), images.ts
|
||||
(icon_wood.webp/iconWoodSrc видалені — стали
|
||||
осиротілими після заміни на resourceCounterBgSrc)
|
||||
дизайнерський плейт лічильника), weapon_hud_bg.webp,
|
||||
weapon_icon_bat.webp, zombie_head_icon.webp,
|
||||
images.ts (icon_wood.webp/iconWoodSrc видалені —
|
||||
стали осиротілими після заміни на resourceCounterBgSrc)
|
||||
resources/fonts/ - PassionOne-Black.otf (з temp/) — див. "gameFont"
|
||||
нижче
|
||||
resources/vfx/ - VFX_Lootable_Hit.json, VFX_Lootable_Destroy.json
|
||||
(quarks.art префаби, копії з temp/, реально
|
||||
використовуються з коду — див. PropVfxC)
|
||||
@@ -1159,3 +1186,323 @@ canvas-rect гарантовано збігається з тим, що бачи
|
||||
ресурс в різних сценах польоту — тримати спільну константу базового
|
||||
розміру (`export`), а не дублювати магічне число, інакше вони
|
||||
розходяться, як тут.
|
||||
|
||||
## Day 8 (продовження): WeaponHudC, ZombieInvasionHudC, InstallBanner-рестайл, шрифт, ротація (2026-08-13)
|
||||
|
||||
Усе нижче — **ще не закомічено** (тільки `4a22a9b`/`63609ee` в git; це
|
||||
робота вже після другого коміту). `npm run export` вже прогонявся раз
|
||||
успішно (з побічним авто-встановленням `three.quarks`, бо в `export.cjs`
|
||||
своя мережева воркфлоу — див. окремий output_export_browser_en.html).
|
||||
|
||||
### `WeaponHudC.ts`/`ZombieInvasionHudC.ts` — нові статичні/напівстатичні юайки
|
||||
Реалізовані аналогічно `HudC` (окремий контролер на юайку, `init()` з
|
||||
`TestSceneC`). Ассети: `ZombiePunk_Icon-Bottom.webp`+`Tool_2.webp` для
|
||||
зброї, `REF_1.png` (**насправді webp**, розширення джерела — брехня,
|
||||
перевірено по сирих байтах RIFF/WEBP заголовку) для голови зомбі.
|
||||
|
||||
**ZombieInvasionHudC пройшов кілька раундів фідбеку**:
|
||||
1. Спочатку `.zombie-invasion__bar` мав суцільний зелений `background`
|
||||
(статично "повний" від t=0) — користувач: "WARNING_FRACTION чомусь
|
||||
почався тільки коли шкала повністю заповнилась". Причина НЕ в
|
||||
таймінгу (`114000мс з 120000мс` — точно останні 5%, перевірено), а в
|
||||
тому, що шкала і так ЗАВЖДИ виглядала на 100% — різницю "майже" vs
|
||||
"повна" було неможливо побачити. **Фікс**: реальна заливка
|
||||
(`.zombie-invasion__track` з `overflow:hidden` + `.zombie-invasion__fill`,
|
||||
росте `width:0%->100%` з `right:0`, стартує в ТОЙ САМИЙ тік з тією ж
|
||||
тривалістю, що й голова — їхні межі математично завжди збігаються, без
|
||||
пофреймової синхронізації).
|
||||
2. Голова мала бути БІЛЬШОЮ за саму шкалу (`0.24 * width` проти
|
||||
`0.15 * width` висоти бару) — але `.zombie-invasion__bar` мав
|
||||
`overflow:hidden` для заливки, що обрізало б і голову. **Фікс**: голова
|
||||
винесена сиблінгом `.zombie-invasion__track` (не її дитиною) — обрізає
|
||||
тільки заливку/флеш, не голову.
|
||||
|
||||
### InstallBanner (SDK-компонент) — свідомо НЕ переписаний, лише CSS-рестайл
|
||||
Круглий портрет персонажа + кнопка "INSTALL" знизу — це **не наша**
|
||||
юайка, а SDK `InstallBanner` (`node_modules/@hitplay/playable_template`,
|
||||
підключений в `beforeResourcesLoadedCb.ts`) з реальним кліком
|
||||
(`AnalyticsC.sendDownload()` -> `Template.end()`) і власною
|
||||
конфіг-системою (`src/configUIParams/installBanner.ts`, `upload_file`
|
||||
+ X/Y/scale-відсотки окремо для portrait/landscape — реальні значення це
|
||||
**треті числа** в кожному `values: [min, max, default]`). Користувач
|
||||
попросив "уніфікувати" з іншими юайками — явно спитав через
|
||||
`AskUserQuestion`, чи переписувати логіку самому, чи тільки CSS —
|
||||
**вибрав тільки CSS-рестайл** (безпечний варіант). Додано лише
|
||||
адитивні властивості (`filter: drop-shadow`, `-webkit-text-stroke` на
|
||||
`.bannerButtonText`) — нічого, що конфліктувало б з інжектованим SDK-стилем.
|
||||
|
||||
**⚠️ Знахідка: purgecss мовчки вирізає `.bannerButton`, але не `.bannerLogo`/`.bannerButtonText`**
|
||||
При білді (не тільки в dev) `purgecss` скановує лише `src/**/*.{js,ts,tsx}`
|
||||
+ `**/*.html` на предмет "чи цей клас реально використовується" — а
|
||||
`InstallBanner`'s класи призначаються в JS всередині ВЖЕ мінифікованого
|
||||
SDK dist-бандла (не в нашому `src/`). Емпірично перевірено в реальному
|
||||
білд-виводі (`export/index.html`): `.bannerLogo{filter:...}` і
|
||||
`.bannerButtonText{...}` виживають, а `.bannerButton{filter:...}` — ні,
|
||||
навіть як окреме правило. Ймовірна причина: мінифікатор пакета
|
||||
де-дублював рядок `"bannerButton"` (4 похідні: сам +
|
||||
`Holder`/`Img`/`Text`) на спільний префікс, тож він більше не існує
|
||||
цілим рядком у бандлі — `"bannerLogo"` (лише 2 похідні) не досяг порогу
|
||||
для такої оптимізації. Поза нашим контролем (сторонній пакет) — просто
|
||||
не писати CSS-правила під `.bannerButton` окремо, вони будуть мертвим кодом.
|
||||
|
||||
### `gameFont` нарешті став реальним шрифтом
|
||||
`font-family: gameFont, sans-serif` використовувався в `main.css`/`ui.css`
|
||||
з самого початку проєкту, але `gameFont` НІКОЛИ не був заведений через
|
||||
`@font-face` — тихо відкатувався на дефолтний sans-serif усюди. Користувач:
|
||||
"весь юай має використовувати шрифт PassionOne-Black, він у нас є в
|
||||
temp". Додано `@font-face` в `main.css` (`src/resources/fonts/PassionOne-Black.otf`)
|
||||
під іменем `gameFont` — усі існуючі посилання почали резолвитись сами,
|
||||
без жодної іншої зміни. Технічний нюанс: для шрифтів (на відміну від
|
||||
`images.ts`/`ConvertToBase64WhenRelease`-паттерна) НЕ треба нічого
|
||||
особливого — `assetsInlineLimit: 100000000` в `vite.config.js`
|
||||
(через `defineConfigTemplate`) вже інлайнить будь-який `url()` в CSS як
|
||||
base64 і в dev, і в білді. Перевірено прямо в білд-виводі (не на око).
|
||||
|
||||
### `--lvh`/`--lvw` замість сирого `vh`/`vw`/`vmin` — ротація/адаптивність
|
||||
Користувач (Day 8 чекліст, "All UI elements must be adaptive to changing
|
||||
device rotation"): розвернув екран — нічого не змінилось. **Знахідка**:
|
||||
SDK має `OrientationC` (`node_modules/@hitplay/playable_template`), який
|
||||
під лок-режимом орієнтації обгортає сторінку в
|
||||
`transform: rotate(-90deg)...`, щоб контент лишався візуально портретним
|
||||
навіть на фізично горизонтальному екрані. Сирі `vh`/`vw`/`vmin`
|
||||
**ігнорують transform батьків** і завжди рахуються від фізичного
|
||||
(неповернутого) вьюпорта — тож будь-який розмір у `vh` стає неправильним
|
||||
щойно лок реально спрацює. `OrientationC` для цього тримає `--lvw`/`--lvh`
|
||||
("логічні" версії, коректно стежать за поворотом; в Adaptive-режимі без
|
||||
локу — просто дорівнюють фізичним vw/vh, тобто нічого не коштують) —
|
||||
той самий підхід, що вже й в `InstallBanner.ts` (`--lvw` в коментарях
|
||||
"physical vw doesn't follow the orientation lock"). Усі `--*-width` в
|
||||
`ui.css` тепер `calc(var(--lvh, 100vh) * ratio)`.
|
||||
|
||||
**⚠️ Важливо**: дефолт в `src/configUIParams/orientation.ts` — **"Adaptive"**,
|
||||
НЕ лок. У цьому режимі `--lvh == vh` і фікс вище нічого не змінює
|
||||
візуально прямо зараз — це радше "правильно про запас", коли/якщо
|
||||
проєкт зрештою поставлять на Portrait Lock (майже неминуче для
|
||||
вертикального плейбла). Коли користувач після цього фіксу все одно
|
||||
сказав "нічого не змінилось, юайка так само зосереджена в центрі" —
|
||||
попросив **медіа-правила** замість покладання на `--lvh`/лок-механізм.
|
||||
**Фінал**: кожна з трьох юайок (`resource-hud`/`weapon-hud`/`zombie-invasion`)
|
||||
тепер має власний `@media (orientation: landscape) { ... }` блок одразу
|
||||
після portrait-правила, що перевизначає `top`/`left`/`right`/`bottom` і
|
||||
`--*-width` — незалежно від `OrientationC`/локу, реагує на реальне
|
||||
співвідношення сторін вьюпорта. Значення в landscape-блоках зараз лише
|
||||
дублюють portrait як стартову точку — **ще НЕ підтверджені користувачем
|
||||
візуально**, він вже почав підкручувати `.resource-hud`'s landscape
|
||||
`--hud-width` (з `0.09` на `0.19` — бачив у diff, не сам робив).
|
||||
|
||||
### Стан на кінець цієї сесії
|
||||
- Working tree: `src/configUIParams/installBanner.ts` (можливо просто
|
||||
line-ending, не досліджував — не моя зміна), `TestSceneC.ts`,
|
||||
`main.css`, `ui.css`, `images.ts` — модифіковані; `WeaponHudC.ts`,
|
||||
`ZombieInvasionHudC.ts`, `resources/fonts/`, три нові `.webp` — нові.
|
||||
**Не закомічено.**
|
||||
- `stats.html` — як завжди, build-артефакт, свідомо не в git.
|
||||
- Наступний крок, якщо буде запит: підтвердити/підкрутити landscape
|
||||
`@media`-значення разом з користувачем, коли він реально побачить це
|
||||
на розгорнутому екрані.
|
||||
|
||||
## Health bar для дестройбл-елементів (2026-08-13)
|
||||
|
||||
Референс-скріншот: прямокутний хелз бар з бордером, синя заливка HP,
|
||||
чорним — вже відняте попередніми ударами, білим — відняте саме поточним
|
||||
ударом (з коротким затуханням у чорне), число нанесеного урону над баром.
|
||||
Нехай 10 урону за удар, 100хп у цілого ящика.
|
||||
|
||||
### `BreakablePropC` — перехід з дискретного лічильника хітів на HP
|
||||
`HITS_PER_STAGE`/`hitsOnStage` повністю видалені. `BreakableProp` тепер
|
||||
несе `currentHp`/`maxHp` (`MAX_HP = 100`, `export`-нутий, щоб `HealthBarC`
|
||||
рахував той самий `0..1` дріб без дублювання числа) + `startStageNumber`/
|
||||
`totalPossibleStages` — реальні номери з `_SN` у назвах стейдж-нод (не
|
||||
вигадані), з яких рахується, скільки HP пошкоджений з коробки крейт вже
|
||||
має "по дефолту" (пошкоджені S2/S3-старт крейти стартують не з 100).
|
||||
`hit()` тепер: відняти `HIT_DAMAGE`, повідомити `HealthBarC.onHit(...)`,
|
||||
знищити на HP<=0 (раніше — "просунувся за останній стейдж"), інакше —
|
||||
перевести `stageIndex` на `Math.floor((1 - currentHp/maxHp) *
|
||||
totalPossibleStages)` (з відступом на `startStageNumber`), змаплений у
|
||||
межі власного (можливо короткого) масиву стейджів.
|
||||
|
||||
### `HealthBarC.ts` — новий контролер, world-tracking DOM-бари
|
||||
Одна мапа `BreakableProp -> BarInstance`, живиться з `BreakablePropC.hit()`
|
||||
через `onHit`/`onDestroyed` (аналогічний DI-паттерн до `ResourceC.setFlyTarget`).
|
||||
|
||||
**Позиціювання**: `position:fixed` + сирі px з `canvasRect` (та ж техніка,
|
||||
що й `HudC.getWorldAnchorPosition`, лише в протилежний бік — тепер
|
||||
винесена в `src/utils/screenWorldProjection.ts`, обидва напрямки). Точка
|
||||
прив'язки — реальний `Box3().setFromObject(prop.root)` (верх+центр X/Z),
|
||||
не вгаданий офсет.
|
||||
|
||||
**Три кольори — чистий CSS, без пофреймової JS-анімації**: `.health-bar__white`
|
||||
й `.health-bar__blue` — два накладені div. На кожен хіт: білий миттєво
|
||||
(`transition-duration: 0s`) стрибає на ПОПЕРЕДНІЙ `%`, форс-reflow через
|
||||
`offsetWidth`, потім і білий (з `transition-delay`), і синій одразу
|
||||
виставляються на ПОТОЧНИЙ `%` — синій доїжджає без затримки, білий
|
||||
"зависає" на старому значенні й наздоганяє з лагом, показуючи чорний трек
|
||||
під собою в проміжку. Ніякого `requestAnimationFrame`/tween — сама
|
||||
CSS-transition timing і є ефектом.
|
||||
|
||||
**Авто-приховування**: `idleTime` рахується щокадру, `>= HIDE_DELAY_S` (2с)
|
||||
без нового хіта — `is-hiding` клас + `FADE_OUT_MS` (250мс) opacity-transition,
|
||||
потім видалення з DOM. Скидається на 0 при кожному `onHit`. `onDestroyed`
|
||||
видаляє бар негайно (порожній бар не має лишатись висіти).
|
||||
|
||||
**Числа урону — кілька раундів фідбеку, фінал**:
|
||||
- Спочатку плавали вгору з затуханням — користувач попросив натомість
|
||||
різку появу непрозорого числа (`-webkit-text-stroke`, не text-shadow-глов)
|
||||
з різким скейл-панчем до 1.5x + ротейтом і поверненням, і тільки ПОТІМ
|
||||
затуханням (не рухом).
|
||||
- Ротейт — послідовно звужувався: спершу довільний напрямок/кут, потім
|
||||
користувач уточнив "тільки по годинниковій стрілці, до 2 години дня"
|
||||
(тобто 0..60°, `--damage-rotate`, рандомізується в JS на кожен спавн,
|
||||
читається в keyframe через `var()`).
|
||||
- **Баг знайдений і виправлений**: затухання на спокої (force=0, у
|
||||
контексті джойстика — не плутати з цим, тут йдеться про сам панч)
|
||||
показувало прозору прогалину замість базового кольору, бо альфа
|
||||
інтерполювалась до 0 — фікс: альфа фіксована, змінюється лише
|
||||
RGB-канал (той самий принцип пізніше повторився і в джойстику, див.
|
||||
нижче).
|
||||
- Тривалість/розмір/швидкість анімації (920мс, +20% розмір шрифту,
|
||||
expo-out крива "швидкий старт — повільний кінець") — прямі числові
|
||||
правки за проханням користувача.
|
||||
|
||||
### `src/css/health-bar.css` — новий файл
|
||||
Слідує тому ж house convention, що й `ui.css` (одна `--health-bar-width`
|
||||
змінна, `--lvh` не сирий `vh`) — **окремо зазначено користувачем не
|
||||
чіпати**: файл (як і `ui.css`) свідомо не отримав landscape
|
||||
`@media`-блоку і досі на `vh`, не `rem`/`%` — відомий, прийнятий
|
||||
відступ від Day 8 чекліста, відкладений на потім.
|
||||
|
||||
## PayZoneC: політ депозиту тепер з голови гравця, не з юайки (2026-08-13)
|
||||
|
||||
Був: політ ресурсу в Pay Zone стартував з `HudC.getWorldAnchorPosition()`
|
||||
(іконка лічильника). Користувач попросив: **з персонажа**, летить від
|
||||
голови вгору й плавно спускається в **центр** зони (не з юайки взагалі).
|
||||
|
||||
`PlayerC.getHeadWorldPosition()` — новий публічний метод, `object.position
|
||||
+ (0, PLAYER_HEIGHT, 0)` — `PLAYER_HEIGHT` вже був реальним заміряним
|
||||
розміром рига (`PLAYER_SIZE.y`), не вигаданим числом, тож верх голови
|
||||
рахується без нової магічної константи. `PayZoneC.playDepositFlight`
|
||||
тепер цілиться в геометричний центр `zoneBounds` (не в pivot самого
|
||||
маркер-ноду — не гарантовано, що він точно в центрі footprint-у), і
|
||||
лишень до прямого lerp додає `Math.sin(t * Math.PI) *
|
||||
DEPOSIT_FLIGHT_ARC_HEIGHT` (той самий трюк дуги, що вже в `ResourceC`) —
|
||||
вгору-і-плавно-вниз замість прямої лінії.
|
||||
|
||||
**Знайдено й виправлено**: `DEPOSIT_FLIGHT_SCALE_MULTIPLIER` був
|
||||
підкручений (`0.3`) під СТАРИЙ політ, де перспективна компенсація
|
||||
(`perspectiveCompensationScale`, camera-distance ratio) відчутно
|
||||
збільшувала розмір за час польоту, бо старт був близько до камери (HUD),
|
||||
а кінець далеко. Тепер старт — голова гравця, приблизно та ж дистанція
|
||||
до камери, що й Pay Zone (камера жорстко слідує за гравцем) — компенсація
|
||||
майже не працює, і `0.3` робив токен практично невидимим. Підняли до
|
||||
`1.3`.
|
||||
|
||||
## Джойстик: редизайн під референс + два реальні баги (2026-08-13)
|
||||
|
||||
Референс: прозора середина, градієнтний бордер, помаранчева точка пальця
|
||||
з підсвіткою навколо. `JoystickC.init()` (SDK-обгортка nipplejs) приймає
|
||||
будь-які опції nipplejs напряму, включно з `color: {back, front}` —
|
||||
кожен рядок йде прямо в `background` відповідного div, підтримує
|
||||
градієнти й навіть `var()`/`calc()` (живі CSS-змінні всередині inline
|
||||
style реально оновлюються).
|
||||
|
||||
**Фінальна реалізація** (`beforeResourcesLoadedCb.ts` + `main.css`):
|
||||
- `back` (кільце) — `conic-gradient(from var(--joy-angle), ...)`, базовий
|
||||
колір однотонний темний, підсвітка (тон точки пальця) лише у широкій
|
||||
дузі навпроти пальця, з `calc()`-інтерполяцією RGB-каналів (не альфи!)
|
||||
за `--joy-force`.
|
||||
- `front` (точка) — суцільний плоский колір, без градієнта/тіні.
|
||||
- Форма кільця (прозора середина) — `mask-image: radial-gradient(...)`
|
||||
з **абсолютними px**, не відсотками — щоб зміна `size` (радіус зони) не
|
||||
розтягувала товщину бордера пропорційно.
|
||||
- Розмір точки пальця (`.front`) — фіксований px-оверрайд, повністю
|
||||
відв'язаний від `size` (nipplejs хардкодить точку як `size/2`, тож
|
||||
збільшення радіуса зони інакше тягнуло за собою і точку).
|
||||
- `JoystickC.onJoysticMove` — окрема підписка (SDK підтримує кілька
|
||||
делегатів на подію, `PlayerC` підписаний окремо на той самий івент для
|
||||
руху) ставить `--joy-angle`/`--joy-force` на `instance.ui.el` щокадру.
|
||||
|
||||
**⚠️ Знайдений і виправлений баг: підсвітка на 90° проти стрілки від
|
||||
реального положення пальця.** `Math.atan2(y, x)` на скрін-координатах (y
|
||||
вниз) і CSS `conic-gradient(from Xdeg, ...)` обидва рахують по
|
||||
годинниковій, але з різною точкою нуля: atan2 — схід (3 година),
|
||||
conic-gradient — північ (12 година). Фікс — плюс 90° один раз, не свап
|
||||
знаку і не переписування напрямку градієнта.
|
||||
|
||||
**⚠️ Знайдений і виправлений баг: підсвітка не зупинялась на межі
|
||||
зони, а продовжувала змінюватись, коли палець вели далі за край.**
|
||||
Трасування в самому nipplejs (`Collection.ts`): `force` рахується з
|
||||
СИРОЇ, необмеженої дистанції дотику (`dist / size`), тоді як
|
||||
`frontPosition` (сама видима точка й кут вище) — з ОБМЕЖЕНОЇ. За краєм
|
||||
кільця `force` продовжує необмежено зростати, хоча точка вже візуально
|
||||
запінена на місці — усі `calc()` розраховані на `force` в межах `0..1`.
|
||||
Це ж переповнення й давало жовтуватий відтінок (RGB-канали переїжджали
|
||||
за цільовий колір). Фікс — один `Math.min(Math.max(force, 0), 1)` перед
|
||||
записом у CSS-змінну, а не clamp у кожному calc() окремо.
|
||||
|
||||
Розмір: `size` (радіус зони) підняли на +50%, потім усі елементи
|
||||
(зона+точка+товщина кільця) зменшені на -30% від того — фінальні числа:
|
||||
`size: 105`, точка `35px`/`-17.5px` margin, кільце `43.4/44.8/46.9/48.3px`.
|
||||
|
||||
## Камера: `CAMERA_OFFSET` підкручений (2026-08-13)
|
||||
|
||||
Користувач попросив камеру ближче, показавши референс-кут. `CAMERA_OFFSET`
|
||||
в `TestSceneC.ts` з `(0, 9, -9)` (45° нахил, дистанція ~12.7) на
|
||||
`(0, 8, -6)` — коротша дистанція, трохи інше (положче) співвідношення
|
||||
Y:Z. Порадив користувачу для самостійного підбору: сам `CAMERA_OFFSET`
|
||||
(єдиний вектор, що визначає і дистанцію, і кут — `CameraFollowC.init()`
|
||||
ставить позицію й раз викликає `lookAt`, більше кут не змінюється) і
|
||||
`camera_fov_p` в редакторі конфігів (дефолт 60, діапазон 30-150) —
|
||||
окремий, незалежний важіль "наближення" через FOV. **Важливо**:
|
||||
`camera_position_p`/`camera_rotation_p` слайдери в редакторі — мертві,
|
||||
`CameraFollowC` перезаписує їх одразу при старті.
|
||||
|
||||
## Day 9-10: рефактор і чистка (2026-08-13)
|
||||
|
||||
Бриф прямо просив "думай як розробник, що передає код іншому" — без
|
||||
зміни логіки/поведінки гри, лише структура/дублювання/коментарі.
|
||||
Погоджений план (`EnterPlanMode`/`ExitPlanMode`) виконаний фазами, кожна
|
||||
верифікована окремим `npx vite build`:
|
||||
|
||||
- **Мертвий код прибрано**: `PayZoneC.getTargetWorldPosition()` (0
|
||||
викликів), увесь `PhysicsC.PhysicsObjPair`/`pair`-поле/
|
||||
`disablePhysicsPair()` (клас був повністю нежиттєздатним — єдине
|
||||
місце, що присвоювало `pair`, саме закомічене); 2 прототипні
|
||||
`console.log` (`PayZoneC`, `ResourceC`). `SparkleFxC`'s `console.debug`
|
||||
на виснаження пулу — свідомо залишений (реальна діагностика
|
||||
деградованого режиму, не сміттєвий лог).
|
||||
- **4 нові утиліти в `src/utils/`** — прибрали дублювання, знайдене між
|
||||
файлами (не новий functionality, лише перенесення існуючої формули
|
||||
без зміни):
|
||||
- `perspectiveScale.ts` — camera-distance-ratio компенсація, була
|
||||
незалежно написана і в `ResourceC` (`toTarget`), і в `PayZoneC`
|
||||
(`playDepositFlight`).
|
||||
- `screenWorldProjection.ts` — world<->screen NDC-математика, була в
|
||||
`HudC` (screen->world, unproject) і `HealthBarC` (world->screen,
|
||||
project) — обидва незалежно читали `canvasRect`.
|
||||
- `tweenChain.ts` — той самий "TweenC.add() обидві ланки окремо"
|
||||
гочтя й бойлерплейт, дослівно повторений у `BreakablePropC` і
|
||||
`SparkleFxC`.
|
||||
- `flashOverlayMaterial.ts` — адитивний флеш-матеріал (клон + white
|
||||
additive overlay), дослівно повторений у `BreakablePropC` і
|
||||
`ResourceC`, разом з дубльованою константою `FLASH_COLOR`.
|
||||
- **Коментарі підчищені** у всіх 16 контролерах, `beforeResourcesLoadedCb.ts`
|
||||
і всіх 3 CSS-файлах — прибрана вся хронологія/цитати чату/"Day N"
|
||||
посилання, лишились тільки короткі WHY-нотатки на дійсно неочевидні
|
||||
речі (усі гочті з цього файлу — TweenC-чейн, glTF dot-stripping,
|
||||
nipplejs force-переповнення, atan2/conic-gradient зсув, MeshBasicMaterial
|
||||
білий-тінт-no-op — лишились, просто по одному разу в коді, не по
|
||||
два-три). Додана одна нова коротка нота в `ui.css` — `.bannerButton`
|
||||
реально мертвий у білді (purgecss-квірк), раніше це знав тільки цей
|
||||
файл.
|
||||
- **Свідомо НЕ зроблено**: домен-розбиття `src/controllers/` на
|
||||
підпапки (gameplay/vfx/ui/core) — розглянуто і відхилено: жодної
|
||||
зовнішньої конвенції під це нема (SDK сам плаский), `resources/` —
|
||||
єдиний прецедент підпапок в проєкті, і той групує по типу ассету, не
|
||||
по домену. Переїзд 16 файлів заради нуля функціональної вигоди —
|
||||
саме "overengineering", проти якого прямо просив бриф.
|
||||
- Два CSS-пункти з попереднього Day 8 аудиту (rem/% замість vh,
|
||||
відсутній landscape-медіазапит у `health-bar.css`) — **свідомо не
|
||||
торкались**, за проханням користувача відкласти.
|
||||
|
||||
Перевірено виключно `npx vite build` після кожної фази (усі 883 модулі,
|
||||
без помилок) — жодного self-testing у браузері, як завжди в цьому проєкті.
|
||||
|
||||
Reference in New Issue
Block a user