andrey pushed to main at andrey/fishing-game 2026-09-21 23:40:59 +03:00
5701685dd7 Этап 45 ревизия: свечение рыб — плавный ramp с потемнением неба + компактный ореол (контур не размывается); лягушки крупнее. (1) glowIntensity(): 0 при nightMix()<=0.35 (старт как у фонаря), smoothstep k²(3−2k) по k=(nm−0.35)/0.55, до 1 при nightMix()>=0.9 — вместо мгновенного включения на порге; drawGlowAura(x,y,r,hex,I) — параметр интенсивности (globalAlpha, ранний выход при I<=0.02 — градиент не создаётся); fishGlow()/drawAmbientFish() — жёсткий гейт nightMix()>0.35 заменён на ramp. (2) Контур: радиус ауры 2.6→1.5 (ambient/bite/hooked; боссовая золотая не тронута), профиль градиента круче (стопы 0→0.55·I, 0.45→0.30·I, 1→0 — свет собран у тела, «шар» не заезжает на силуэт), силуэты светящихся видов — непрозрачные (hooked/bite/approach/out: alpha=1 при sp.glow; ambient: a+(1−a)·glowI — к глубокой ночи 1.0); у локаций 0..3 (glow=null) альфы не менялись. GLOW_RGBA-кэш +поле mid, save/restore и 'lighter' сохранены. (3) Лягушки: frogs[].s 4.5–7 → 9–14 (≈×2, отрисовка drawSwampDecor масштабируется от s), jh 10–22 → 16–30. Пиксель-приёмка (headless, Болото, фоновые рыбы): I монотонна 0.000→0.023→0.502→1.000 (t 0.30/0.55/0.70/0.85), день без свечения, excess(0.55)=7.4 < excess(0.85)=18.6, тело насыщенное sat≈93 / «мыла» 0% (контур чёткий); лягушки bbox 28×21.5 px при s=12 (×2.07), initScenery даёт s∈[9,14]. Проверено: 204/204 PASS exit 0, check.mjs OK. Скриншоты перегенерированы (42 RU + 42 EN; swamp-night заметно «чище»: компактные ореолы). Доки: AGENTS.md (ramp 0.35→~0.9, ореол 1.5/профиль 0.55/0.30, frogs s≈9–14), DEVLOG (блок «Ревизия свечения и лягушек» в Этапе 45). По просьбе пользователя (плейтест на телефоне).
andrey pushed to main at andrey/fishing-game 2026-09-21 22:59:26 +03:00
7f545347b4 Этап 45: локация «Волшебное болото» (id 4, 90 000 🪙) — светящиеся рыбы, лягушки, кувшинки/лилии. (1) Данные: LOCATIONS[4] (тёмно-моховая вода 6 hex, слабая рябь; в массиве ПОСЛЕДНИЙ, по цене — между Озёрами 65536 и Морем 131072); 5 новых видов строго в КОНЕЦ SPECIES (32→37, по одному на редкость r0–r4, у каждого glow:'#hex' — 5 разных цветов): glowfin Светлячок #5ff2ff 8🪙, moonfish Лунная рыбка #b9c8ff 13, emberfin Изумрудный светляк #57ffa8 20, violetlure Фиалковый огонёк #d17bff 38, spiritfin Дух болота #ffe07a 70; SWAMP_IDS/SWAMP_DAY_WEIGHTS/SWAMP_NIGHT_WEIGHTS/SWAMP_SPECIES(_NIGHT) — паттерн LAKE/SEA/OCEAN без пересечений; NIGHT_WEIGHTS — ключи всем 37 id. (2) pickSpecies(): вложенный тернарник → табличный доступ SPECIES_BY_LOCATION(_NIGHT) по save.location + guard (вне 0..4 → Река); роллы 0..3 бит-в-идентичны (lc3/lc4/lc4b/lc4c + речные §9j/M4/M6 не тронуты). (3) Свечение (только ночь): nightMix()>0.35 — тот же порог, что у фонаря; drawGlowAura() (радиальный градиент + 'lighter', save/restore, кэш GLOW_RGBA) — фоновые рыбы болота (AMBIENT_FISH[4] — 7 рыб + palette из 4 цветов, цвет стабильно по индексу), зацепившаяся/вываживаемая (fishGlow — вид с glow), боссовая золотая аура сохранена; карточка — класс glow-card + --glow (только normal-вариант, drop-shadow, не конфликтует с фильтрами вариантов), дневник — drop-shadow на SVG. (4) Декорации: initScenery() ветка i===4 (bank+reed+snag+pine в болотной гамме), ГЛОБАЛЬНЫЕ pads[] (8–14 кувшинок с вырезом, 45% с лилиями — жёлтые/белые/розовые) и frogs[] (3–5, sit→jump по параболе на соседнюю кувшинку, 3–7 с) — очищаются/пересобираются в initScenery() (resize + обе ветки shopClick); updateDecor(dt) — покачивание/прыжки; drawSwampDecor() — ОТДЕЛЬНЫЙ слой после drawWater/drawAmbientFish и до drawBoat (дusk берега не гасит; локальное притухание ночью). (5) Босс: BOSS_BY_LOCATION[4]='spiritfin' (Дух болота, 20–50 кг, ×5 — паттерн Этапа 37). (6) Магазин/i18n/ачивки: тост welcome_swamp (ru/en, тернарник → if/else), ачивки 34→36: swamp_first (bonus:{coinPct:0.02}, locations-based) + swamp_boss (bonus:{}, bosses.spiritfin) → пин achBonus().coinPct 0.16→0.18; species_8 = все 37. (7) Баланс: SWAMP_DAY_WEIGHTS {glowfin:3,moonfish:4,emberfin:28,violetlure:13,spiritfin:4.5}, SWAMP_NIGHT_WEIGHTS {glowfin:2.5,moonfish:2.5,emberfin:20,violetlure:30,spiritfin:4} — Болото 240.3/328.9 🪙 (ночь/день ×1.37), порядок по цене Озёра 194.1/249.0 < Болото < Море 297.3/476.7 в ОБЕ фазы; пины остальных вод не изменились (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). (8) tools/balance.mjs: 8→10 таблиц, +SWAMP_SPECIES(_NIGHT) в return, сводка/пары отношений — сортировка ПО ЦЕНЕ (болото встает между Озёрами и Морем), пины в шапке. (9) Портреты: 5 flat-SVG (каждый — отдельным художником) assets/fish/fish-{glowfin,moonfish,emberfin,violetlure,spiritfin}.svg (viewBox 0 0 160 100, var(--f1..f4,hsl-fallback)); embed-fish.mjs IDS 32→37 (в конец), 37 <symbol> в index.html; fish-preview.html 32→37 карточек. (10) Тесты (тот же коммит): lc1 (37/5 локаций/90000/names/sprites 37/oceanOrder slice(23,32)/swampOrder/swampGlow/swampRar), lc2 (+SWAMP-таблицы, пересечения, nightW 37), lc4d (новый: 3000+3000 роллов болота — все 5 ≥1, чужих нет), lc5 (+location:4 не сбрасывается, location:5→0), lc8w (новый: покупка 90000 + welcome_swamp), lc9 (37), lc10 (mid29), lc11 (новый: glow #rrggbb, 5 цветов различны, веса покрывают id, NIGHT_WEIGHTS — все 37), a22d (36), a36loc (+swamp_first), пин 0.18, §9k2 (+{loc:4, spiritfin, swamp_boss}). 198→204 PASS, exit 0. (11) Скриншоты: gen-screenshots.js +кадры swamp/swamp-night (12→14 × 3 вьюпорта, dayTime 0.3/0.85) — 42 RU + 42 EN PNG (screenshots-wiki/, screenshots-wiki-en/). (12) Доки: AGENTS.md (локации/босс/баланс/баланс-скрипт/награды/портреты/скриншоты), README (5 локаций, 37 видов, 36 ачивок, 204 теста, 14 кадров, mobp-swamp*), KODA.md (SWAMP_*, SPECIES_BY_LOCATION, drawGlowAura/fishGlow/GLOW_RGBA, drawSwampDecor, pads/frogs), DEVLOG (Этап 45), PLAN-SWAMP.md (статус «реализован»). Проверено: 204/204 PASS exit 0, check.mjs OK, balance.mjs — пины без изменений + Болото в цели, emoji-font --check OK (52 глифа, новых emoji нет), ревью @oracle — критичных замечаний нет (.gitignore + .opencode/, fish-preview, осколок комментария species_8 — закрыты в этом же коммите). Миграция сейва не тронута (граница из LOCATIONS.length; location=4 покрыт lc5(f)).
andrey pushed to main at andrey/fishing-game 2026-09-21 18:36:23 +03:00
3e9c5b7b45 Этап 41 ревизия 5 (px узлов — ручная подгонка) + закрытие диалогов по тапу мимо (backdropClose) + тест §X. (1) FISH_SIZE_KNOTS: 0.1 кг → 12 px (0.19× лодки), 0.2 → 16, 0.4 → 20, 0.8 → 24, 1.6 → 36, 3.2 → 48 (0.75×), 6.4 → 64 (= лодка, не тронут), 12.8 → 80, 25.6 → 96, 51.2 → 160, 100 → 256 px (= 4× лодки, не тронут) — мелкие рыбы мельче, средние узлы пересчитаны; интерполяция (линейно по log2 веса) и клампы не менялись: диапазон таблицы = диапазон функции 0.1–100 кг, fishSizeFromW() без правок; босс 20–50 кг → 90–158 px (1.41–2.47×), 1 кг → 27.9 px, диапазон 12..256 px ≈ ×21. (2) backdropClose(el,fn) (секция «КНОПКИ», после Y2-хендлеров): тап по подложке (e.target === сам оверлей, не .panel) закрывает диалог тем же действием, что и кнопка: #shop → closeShop, #resetDlg → «Отмена», #pause → closePause, #gamemenu → «Продолжить», #card → «Отлично!» (вкл. интерстишел); #menu — экран старта, вне списка. Подводный камень: pop-анимация #card (300 мс) сужает hit-area подложки — тест ждёт 400 мс после showCard. Тест §X (tests/test.js, 5 проверок: лавка/пауза/«Меню»/сброс/карточка, вкл. сохранение save.coins при «Отмене» и YG.counts.start +1 при «Продолжить») — 193→198. Проверено: все 11 узлов 0% отклонения, монотонность 2001 точки, клампы (0.05 кг → 12 px, 200 кг → 256 px); 198/198 PASS, exit 0; check.mjs OK; пины balance.mjs без изменений. Скриншоты перегенерированы (36 ru + 36 en; кадр reel 12.5 кг → ~79.5 px ≈ 1.24× лодки). Доки: AGENTS.md (строка backdropClose), DEVLOG (Этап 41 — пятая ревизия: узлы, размеры, 198/198), коммент над таблицей в index.html.
andrey pushed to main at andrey/fishing-game 2026-09-21 15:14:26 +03:00
ea428bb4fb Карточка улова: SVG-портрет рыбы ×2. #card .bigemoji svg 120×75 → 240×150 (моб. ≤420px: 94×59 → 188×118, низкий экран ≤620px: 81×50.6 → 162×101.2 — соотношение 160:100 сохранено). Панель min(92vw,370px) с паддингом 22 px — контентная ширина до 326 px, 240 px влезает; на низких экранах панель скроллится (max-height:92vh). Чисто CSS: роллы/баланс/физика не тронуты. Тесты: пинов на размер портрета нет (M6-пин — href #cardFishUse) — 193/193 PASS, exit 0; check.mjs OK.
andrey pushed to main at andrey/fishing-game 2026-09-20 23:26:43 +03:00
48c54491dd Этап 44: береговые силуэты на горизонте (полный вариант различения локаций) + ревизия Реки. scenery/initScenery() по локации: Река — береговая полоса на всю ширину {k:'bank',h} (трава 12–17 px + тёмная кромка у воды) + хвойный лес в 2 ряда, посаженный на её кромку ({k:'pine',layer,by} — by=waterY−bankH, база ствола); Озёра — холмы {k:'hill',rx,ry} (2–3 дуги за деревьями) + лиственные деревья {k:'tree'}; Море — парусник {k:'ship',dir,v,s} (медленно дрейфует по курсу, паруса светлые) + 3 чайки {k:'gull',y,v,ph} (летят, машут крыльями); Океан — ПУСТО (открытый горизонт без берега). drawScenery() — между drawSky() и drawWater() (вода перекрывает базу силуэтов); ночь — dusk()=hexLerp(·,'#0b1220',nm*0.8) гасит силуэты, чайки почти гаснут; дрейф — updateDecor(dt). Река без волн (ревизия): LOCATIONS[0].waves — все нули, drawWater() рисует линию только при amp>0/amp2>0 — спокойная вода, ровный край. Провозировка initScenery(): resize(), обе ветки смены локации shopClick (рядом с initFish), кадры lake/sea/ocean в gen-screenshots.js (без него кадр Моря показал бы лес с Реки). Скриншоты перегенерированы (72 PNG: screenshots-wiki/ + screenshots-wiki-en/). Чисто визуал: роллы/баланс/физика не тронуты. Тесты: 193/193 PASS, exit 0; check.mjs OK; balance.mjs — пины без изменений. Приёмка: headless 1280×720, 4 локации × день/ночь + кроп-контроль горизонта (пиксельная выборка неба — чистый градиент, «точки» в превью — артефакт даунскейла). Доки: DEVLOG (Этап 44), AGENTS.md (строка «Локации» — waves/сценарий silhouette + вызовы initScenery), README (строка локаций — «свой берег»).
andrey pushed to main at andrey/fishing-game 2026-09-20 21:44:44 +03:00
4e7a9ddab0 Этап 43: визуальное различение локаций (лёгкий вариант). Вода различима по цвету (Море — светлая бирюза #41b1e8/#2287c9/#0b3d6e, Океан — глубокий тёмно-синий #1a5fa8/#0c3d74; Река/Озёра не тронуты — тест пинит только формат 6 hex), характер волн поверхности по локации: LOCATIONS.waves {amp,amp2,freq,freq2,speed,speed2} в drawWater() — Река мелкие гребни, заметно текут в сторону (speed 3.2), Озёра медленная гладь (1.2 px), Море умеренная волна (3.5 px), Океан крупные зыби (6–8 px); фоновые рыбы по воде: AMBIENT_FISH[4] {n,sMin,sMax,hMin,hMax} в initFish() — Река 9×8–22 как было, Озёра 9×10–26 зелёные, Море 8×12–32 синие, Океан 6×18–44 крупные тёмно-синие; initFish() добавлен в обе ветки смены локации shopClick (buylocation/selectlocation) — раньше рыбы не знали о смене воды. gen-screenshots.js: +кадры sea/ocean (10→12 кадров, save.location=2/3 + initFish), кадр lake и сброс — initFish. README: строка локаций «своя вода (цвет, характер волн, рыбы в толще)» + 3 изображения lake/sea/ocean, «12 кадров × 3 вьюпорта». Скриншоты перегенерированы: screenshots-wiki/ и screenshots-wiki-en/ по 36 PNG. Чисто визуал: роллы/баланс/физика не тронуты (небо/облака/лодка — общие, по выбранному варианту). Тесты: 193/193 PASS, exit 0; check.mjs OK; balance.mjs — пины без изменений (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). Доки: DEVLOG (Этап 43), AGENTS.md (строки «Локации»/«Скриншоты»).
andrey pushed to main at andrey/fishing-game 2026-09-20 20:41:15 +03:00
cfdb93bf7c Этап 41 ревизия 4 (финальная): размер рыбы — узловая таблица по степеням двойки, интерполяция по log2(веса). fishSizeFromW(w) + FISH_SIZE_KNOTS=[[0,16],[1,20],[2,25],[3,35],[4,48],[5,64],[6,80],[7,100],[8,120],[9,170],[log2(1000),256]] ([log2(w/0.1), длина px]) — явная таблица пользователя (веса степени двойки, «погрешность 10%»): степенная шкала ревизии 3 не покрыла таблицу в середине (на 25.6 кг было бы +24% к цифрам; локальный показатель кривой 0.26..0.61) — заменена узлами. Длина силуэта = 2.45·fs (тело 2·fs + хвост), интерполяция линейна по log2(w) — узлы бьются ТОЧНО (0% отклонения, проверено: 16/20/25/35/48/64/80/100/120/170/256 px), кривая монотонна (1000 точек); веса вне 0.1–100 кг клампятся в края (нижний кламп — только золотая рыбка 0.05–0.1 кг). Распределение: 0.1 кг → 16 px (0.25× лодки), 0.2 → 20, 0.4 → 25, 0.8 → 35, 1.6 → 48, 3.2 → 64 px (= лодка), 6.4 → 80, 12.8 → 100, 25.6 → 120, 51.2 → 170 px, 100 кг (кит max) → 256 px (4× лодки); 1 кг → 39.2 px, 10 кг → 92.9 px; босс 20–50 кг → 113–168 px (1.77–2.6×). Диапазон 16..256 px = ×16. Тесты: пинов на размер силуэта нет — 193/193 PASS, exit 0; check.mjs OK; скриншоты пересняты (кадр reel: 12.5 кг ≈ 99 px ≈ 1.55× лодки); узлы 100/3.2/0.1 кг проверены живыми кадрами headless-Chromium (численный контроль 16.0/64.0/256.0 px). Доки: DEVLOG (Этап 41 — таблица, интерполяция, пометки ревизий 3/4).
andrey pushed to main at andrey/fishing-game 2026-09-20 19:32:56 +03:00
31d60a6333 Этап 41 ревизия 3: 100 кг → 256 px (4× лодки), 1 кг → 20 px — степенная шкала. fishSizeFromW(w)=(3.95+16.05*max(0.1,w)^0.5981)/2.45 — по ДЛИНЕ силуэта (длина = 2.45·fs): якоря 0.1 кг → 8 px (не тронут), 1 кг → 20 px, 100 кг → 256 px = 4× лодки 64 px (было 128 = 2×). Буквально квадратичная шкала 3 якоря не держит монотонно (парабола по w: пик ~420 px на 61 кг, затем схождение к 256 px на 100 кг — кит меньше «средней» рыбы; квадратичная по ln w: провал до ~4 px у 0.2 кг) — степенная A+B·w^k точна по всем трём якорям и монотонна (k≈0.598, A≈3.95, B≈16.05). Распределение: 5 кг → 46 px (0.72× лодки), 10 кг → 67.6 px (1.05×; размер лодки достигают ~9.1 кг), 20 кг (босс min) → 100 px (1.57×), 50 кг (босс max) → 170.6 px (2.67×), 100 кг (кит max) → 256 px (4×). Диапазон 8..256 px = ×32 (было ×16; в исходной формуле ×2.7). На мобильном 360 px кит ≈ 71% ширины экрана. Тесты: пинов на размер силуэта нет — 193/193 PASS, exit 0; check.mjs OK; скриншоты пересняты (кадр reel: 12.5 кг ≈ 77 px ≈ 1.2× лодки); якоря 100/1 кг проверены живыми кадрами headless-Chromium. Доки: DEVLOG (Этап 41 — формула, таблица размеров, пометка ревизии и обоснование выбора шкалы).
andrey pushed to main at andrey/fishing-game 2026-09-20 19:09:53 +03:00
203694a30c Этап 41 ревизия 2: минимум 0.1 кг → 8 px длины силуэта (fs 8→3.27). fishSizeFromW(w)=(8+120*(max(0.1,w)-0.1)/99.9)/2.45 — шкала теперь линейна по ДЛИНЕ силуэта (длина = 2.45·fs), якоря: 0.1 кг → 8 px (было 19.6 px — «ещё меньше»), 100 кг → 128 px = 2× лодки 64 px (не тронут). Новое распределение: 1 кг → 9.1 px (0.14× лодки), 5 кг → 13.9 px (0.22×), 10 кг → 19.9 px (0.31×), 20 кг (босс min) → 31.8 px (0.50×), 50 кг (босс max) → 67.9 px (1.06×), 100 кг → 128 px (2×); размер лодки (64 px) достигают ~47 кг. Диапазон 8..128 px = ×16 (было ~20..54 px = ×2.7): мелочь — точечная, разброс дали тяжёлые 20–100 кг. Баланс/тесты: не затронуто — 193/193 PASS, exit 0; check.mjs OK; скриншоты пересняты (кадр reel: 12.5 кг ≈ 23 px ≈ 0.36× лодки). Доки: DEVLOG (Этап 41 — формула/таблица обновлены, пометка ревизии).
andrey pushed to main at andrey/fishing-game 2026-09-20 19:00:58 +03:00
2734998854 Этап 41 ревизия: лог-шкала размера рыбы → линейная. fishSizeFromW(w)=8+44.2*(max(0.1,w)-0.1)/99.9 вместо 8+44.2*log10(max(0.1,w)/0.1)/3 — лог поднимал средние рыбы до «почти лодка» (1 кг → 0.9×, 10 кг → 1.4×): «все рыбы сильно большие». Якоря не изменились: 0.1 кг → 8 (минимум), 100 кг → 52.2 (128 px = 2× лодки 64 px). Линейное распределение: 1 кг → 8.4 (0.3×), 10 кг → 12.4 (0.5×), 20 кг (босс min) → 16.8 (0.6×), 50 кг (босс max) → 30.1 (1.2×), 100 кг → 52.2 (2×) — размер лодки (64 px) достигают ~41 кг. Мелочь осталась мелкой (как в старой формуле 8+(w/wMax)*10+rarity), разброс дали тяжёлые 20–100 кг. Баланс/тесты: не затронуто — 193/193 PASS, exit 0 (прогон поверх Этапа 42); check.mjs OK; скриншоты пересняты (кадр reel: 12.5 кг ≈ 33 px ≈ 0.5× лодки). Доки: DEVLOG (Этап 41 — формула и таблица размеров обновлены на линейную, помечена ревизия).
2329dd9a21 Центрирование SVG-портрета на карточке улова: #card .bigemoji svg — margin:0 auto. Портрет (блок фиксированной ширины 120px) прижимался к левому краю: text-align:center у .panel центрирует только текст, на блочный SVG не действует (.bigemoji — display:block на всю ширину). Адаптивные размеры (94px/81px в media-запросах) наследуют правило. Игровая логика не тронута (визуальный фикс). Тесты: 193/193 PASS, exit 0; check.mjs OK.
Compare 2 commits »