Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
15.05.2023
Враження від Greensock
…Вчорашнє розуміння про Greensock доповнилось сьогодні тим, що в onUpdate
краще зовсім нічого не перераховувати — саме тому, що ця функція може бути викликана в неочікуваний час та в невизначеному порядку. Як тільки переніс всі обчислення з onUpdate
в render
, відразу зникли баги. А то було таке, що в прямому порядку анімація проходить нормально, а у зворотному — бардак.
Тож тепер підхід такий: Greensock собі анімує все, що потрібно, а потім я в функції render
оновлюю сцену відповідно до поточної мітки, переношу значення в потрібні місця, та, власне, потім роблю малювання. Тепер все передбачувано.
Після цього відчувається користь від бібліотеки: рівень абстракції підвищився. Більше не потрібно думати про стикування частин та про перенос глобальної позиції в локальну до етапу. Можна легко додавати до анімації нові етапи та експериментувати (краще наближати камеру та повертати одночасно? або послідовно? )
Наступним кроком, знайшов ресурс Natural Earth, на якому містяться, окрім іншого, бази даних по різних географічних обʼєктах. Мені цікаві кордони держав та міста. Все це можна завантажити в невідомому мені досі форматі shapefile, до якого, на щастя, є парсери як для JavaScript, та і для Go.
PS: а знаєте, що офісне крісло може вимикати монітор? В цьому винний електростатичний розряд, який створює механізм підйому. Звучить нереально, але в мене таке дійсно відбувається час від часу — встаю з крісла та монітор вибиває. Якби не натрапив випадково на пост, то це б залишалось таємницею. А так, спробую замінити кабель до монітора.
14.05.2023
Бібліотека анімації Greensock
Відкриття дня - бібліотека Greensock. Вона надає зручну структуру для анімації. Я вже мало не написав свою, але випадково побачив в прикладах Greensock та, на щастя, це саме те, що мені було потрібно.
В чому моя задача? Анімація з декількох етапів потребує відстеження як поточного етапу, так і положення в ньому. Greensock дозволяє задавати ці етапи декларативно, та сама бібліотека піклується про їх впорядкування. До речі, вона підтримує й анімацію прокруткою, якою я займався вчора. І помʼякшення анімації вбудоване.
Як воно працює з Three.JS? Взагалі вся анімація являє собою інтерполяцію значень. В базових прикладах по Greensock значення містяться в СSS, але насправді вона вміє інтерполювати будь-які числові атрибути довільного обʼєкту. В тому числі, й векторів Three.JS - або просто звичайних обʼєктів, якщо це зручно. Коли над значеннями, що інтерполюються, потрібно проводити додаткові дії, то їх можна описати в функції onUpdate
.
Що мені не дуже подобається: інтерполювати можна тільки по одному обʼєкту, а з Three.JS зазвичай треба комбінувати декілька (або навіть просто position
та rotation
). В такому випадку створюю окремий обʼєкт-ціль інтерполяції, а з нього вже в onUpdate
розкидую значення куди треба.
Ще довго шукав, як же ж робити переходи від сцени до сцени, тобто наприклад з глобуса на карту. Це ускладнюється ще й тім, що з анімацією за прокруткою цей перехід може трапитись в обидва боки. А ще, як виявилось, функція onUpdate
може викликатись не тільки для поточного етапу, тому там не можна робити логіку визначення сцени. Потім знайшов систему міток та функцію currentLabel, яка саме відстежує поточний етап анімації. Тут ідея така: під час render
перевіряю поточну мітку, та готую сцену для неї, якщо мітка помінялась.
3D-графіка - приємна розвага після системного програмування, поки не примушує згадувати про всякі векторні добутки та кватерніони, про які я вже років 15 не чув.
13.05.2023
Анімація за прокруткою
Черговий прогрес по тревел-постам — реалізував анімацію карти за прокруткою. Подивився оцю нещодавню статтю з NYTimes та зрозумів, що саме цього не вистачало для режисованого, але все ж контрольованого користувачем відображення. (Анімація, яку я маю на увазі, починається після перших параграфів статті, до неї треба ще докрутити.)
Як я це робив. Щоб реєструвати прокрутку, роблю елемент необхідної висоти — саме його фізичний розмір буде визначати тривалість анімації. Всередину розташовую власне полотно. Полотно за розміром збігається з вікном. Його позиціювання залежить від положення прокрутки — це або абсолютне позиціювання нагорі чи внизу контейнера, або — повноекранне fixed
, при якому й відбувається анімація.
Щоб стежити за прокруткою, слухаю звичайну подію scroll
. Щоб заощадити ресурси, це робиться тільки тоді, коли елемент з картою видимий; для цього існує цікавий клас IntersectionObserver.
Далі позиція прокрутки перекладається на відсоткову, і починається цікава частина. До цього часу моя анімація була повністю заскриптована, та просувалась за допомогою requestAnimationFrame. Натомість для анімації за прокруткою необхідно задати функцію стану сцени від часу. Я майже все так і робив, от тільки з обертанням карти вийшли деякі складнощі. Окремо треба описати переходи від сцени до сцени, як в прямому, так і у зворотному напрямку — додавання та видалення обʼєктів.
12.05.2023
Команда apt-get satisfy та інші цікаві пакетні менеджери
Дізнався на днях про команду apt-get satisfy
. Нею можна вказати версію пакета приблизно, як я це звик робити в Rubygems або NPM. Наприклад: apt-get satisfy 'knot-resolver (>=5.6.0)'
. Мені це було потрібно, щоб переконатись, що правильна версія пакета буде встановлена в докерфайлі. Взагалі лінтер hadolint радить вказувати версію явно. Але при такому підході докерфайл доведеться міняти, коли версія пакета в репозиторії оновиться — чого я не хочу робити без потреби.
Команда ця чомусь мало відома, навіть довелось відповісти про неї на Ask Ubuntu річної давнини. Зʼявилася вона десь у 2019 році.
Якщо вже зайшло про пакетні менеджери, то на Windows необхідно знати про chocolatey. Завдяки цій програмі можна як встановити, так і оновити багато популярних додатків автоматично. Особливо це корисно для налаштування компʼютерів родичам. Замість того, щоб лазити по системі та оновлювати все підряд, достатньо один раз запустити choco upgrade
. Так само однією командою можна встановити пачку необхідних програм.
А на macOS є Homebrew Cask. Я їм не користуюсь, але тільки що перевірив та там є чимало додатків — більше, ніж я думав — наприклад, ось Setapp.
Чим я на Маці користуюсь, то це додатком MacUpdater. В нього зворотний підхід — він сам знаходить в системі всі встановлені додатки, та вміє їх оновлювати. Це набагато ефективніше, ніж погоджувати оновлення кожного додатку окремо. Також не так давно зʼявилася можливість завантажувати та встановлювати додатки. Але все це MacUpdater робить в напівавтоматичному режимі, тому розгорнути пачку додатків однією командою не вийде.
…А ще MacUpdater теж є на Homebrew Cask. We need to go deeper!
11.05.2023
На що гарний Golang у вебдодатках?
Я вже писав статтю про те, на що гарний Ruby on Rails, та я все ще вважаю Rails правильним вибором для вебдодатка. Тобто, якщо додаток написаний на Rails, то скоріше за все не доведеться його переписувати на щось інше.
Але уявимо, що вам треба переконати мене, що додаток треба писати на Go, а не на рельсі. Ой, важко це буде зробити. Бо Go не підготований для створення вебдодатків. Починаючи з того, що мова ця не така гнучка (див. статтю). Але також, на Go не вистачає відразу декількох інструментів, які є в Ruby on Rails. Це й міграції для бази. Й шаблонізатор. Й інтеграційні тести. І це тільки те, чого мені найбільш не вистачає. Писати вебдодаток на Go - технічно можливо, але безглуздо.
Тому пропоную дивитися на роль Go інакше, та переписувати на Go свою базу даних. Бо сильна сторона Go - це утримання складного та великого стану.
В Rails ми делегуємо утримання стану на базу даних. На такому розділенні праці побудований весь сучасний інтернет — тож можна сказати, що воно надзвичайно ефективне. Втім, зустрічаються випадки, коли база не справляється з потребами додатка. Може, бізнес-логіка надто складна, може, обмеження швидкодії не влаштовують. В таких випадках можна пошукати іншу базу, та я б це й радив робити. Можна почати програмувати всередині бази, це теж працює.
Але програмування в базах даних, порівняно зі звичайним, суцільний жах. Тестів немає, деплою немає, і так далі. Тому простіше було б реалізувати логіку стану безпосередньо в додатку. Ось тут вже можна впевнено брати Go. В Go чудова модель рівночасності, яка дуже корисна для керування складними структурами стану. Зробити власну базу легше, ніж здається, бо універсальна база нам не потрібна — тільки те, що використовує додаток. Власне, так NoSQL бази й зʼявляються.
(Звісно, це не єдине застосування Go. Я міркую з боку вебдодатків.)
10.05.2023
Точна перевірка як антипаттерн
Виявив, на велике диво, що в нас в черзі задач бовтається задача ще з лютого місяця. Причиною стало особлива бізнес-логіка, по якій задача має N
шансів отримати помилку та спробувати пізніше, а на N+1
спробу повинна видати “жорстку” помилку та остаточно закінчитись. (Так, зазвичай черги мають таку функцію вбудовану, але тут не зовсім стандартна черга.)
За цією логікою, задача не могла залишатись в черзі більше як добу. Що трапилось? Умова остаточного виходу була з перевіркою на рівність: attemptNumber == N+1
. Через незрозумілу мені ситуацію, логіка на N+1
спробі не спрацювала — скоріш за все, команда на видалення з черги не була опрацьована. Та на N+2
, N+3
, N+100
-й спробі задача призводила тільки до “мʼякої” помилки.
Інтуїтивно мені завжди хочеться зробити максимально чітку перевірку — якщо я знаю, що гілка має трапитись на N+1
спробі, то так і треба написати? Власне, сьогоднішній випадок показує, що ні. Треба осягнути всі можливі значення змінної, та визначити, що має трапитись в кожному. Тут у нас є дві множини значень, які розгалужують логіку. Все, що до N
, створює “мʼяку” помилку. Все, що після N
, створює “жорстку”. Саме це й має висловлювати умова: attemptNumber > N
.
…Окремий випадок — це дробові числа. Їх взагалі не можна надійно порівнювати точно через особливості обчислень з рухомою комою. Підійде або наближене порівняння: abs(a-b) < EPSILON
, де EPSILON - незначне маленьке значення, або ж, знов-таки, порівняння більше/менше.
09.05.2023
Останні, поки що, міркування про ВР
Пройшов Half-Life: Alyx, потім подивився відео як воно з шоломом грається (бо тепер без спойлерів)… Ну так, безперечно, суть цієї гри саме в ВР. От, наприклад, щоб відкрити ящик з припасами, треба розвʼязати простеньку головоломку на повертання кулі. В моді без ВР такі ящики відкривалися просто кнопкою. З іншого боку, стрілянина досить примітивна, що особливо помітно на кінці гри, коли її стає багато. Зброї, як виявилося, всього три різновиди, тобто ніякої тактичної глибини немає. Як шутер, гра на четвірку з мінусом.
Проте я радий, що вдалося пограти, побачити сюжет та краєвиди. Бо моя головна проблема з Half-Life: Alyx була в тому, що ВР мені не цікавий, а тут виходить, що команда Valve вирішила вкластися саме в ВР-гру. Хоча, на цей час, можна сказати, що ВР стає більш нішевою технологією, а не такою, що замінить ігри на моніторі та телевізорі. (Та насправді найбільше гравців та грошей зараз в смартфонах.)
Чому не люблю ВР? Головним чином, не хочу бути ще більше ізольованим від світу — чесно кажучи, проводити час абсолютно зануреним в гру мене навіть лякає. Я й так багато часу сиджу за екраном. Також, хоч ВР й збільшує занурення, але через це суттєво обмежує потенціал ігор. Мої улюблені жанри (а саме, soulslike та boomer shooter) потребують свободи рухів, яку ВР не може забезпечити. Та чого там, навіть стрибати по Morrowind зі швидкістю коня у ВР не вийде. Тому тенденція переходу ігор у ВР мене тривожила. Поки ця тенденція була. Але зараз виглядає так, що ВР буде розвиватися своїм шляхом та розкривати свій унікальний потенціал.
Взагалі, як користувачу, мені більше цікава доповнена реальність. Під якою я маю: реальність, на яку накладаються “живі” цифрові елементи. Причому, бажано, не окулярами чи шоломом, а саме вкрапленнями цифрового змісту — яких в нас вже й так багато, від екранів телефонів до транспортних табло, реклами та навіть світлофорів. Такого я б хотів бачити більше. Не шоломів.
08.05.2023
Як зібрати гаражний VR-комплект за декілька тисяч гривень
…Насправді це моя друга спроба пограти в Alyx. До цього я зібрав собі VR “з підручних засобів” та навіть успішно… Було це ще у 2020-му, карантин, робити не було чого. Ось стисла інструкція:
-
Шолом. Одним з перших способів відвідати ВР був Google Cardboard. Це, попросту кажучи, коробка з картону та пари лінз, у який можна покласти смартфон та, за наявністю сумісних програм, мати справжню віртуальну реальність з нормальним трекінгом голови. Якість зображення залежала від роздільної здатності смартфона, та з айфоном виходило зовсім непогано. В теорії, Cardboard розрахований на дуже короткочасну роботу, тому його положено тримати біля очей руками. Проте вистачає моделей з ременями та поролонками.
-
З усіх Cardboard-програм нам буде цікава iVRy. То є драйвер, що підключає SteamVR до Google Cardboard. В ідеалі, потрібне дротове підключення, для чого в шоломі робиться технічний отвір для кабелю. В принципі, це спосіб гривень за 500 пограти в ігри з VR екраном, тож якщо вам цікаво — то нема проблем спробувати, наприклад, Skyrim VR.
-
Контролери. Розумним було б на цьому зупинитися. Але ж Half-Life: Alyx, як і більшість “справжніх” ВР-ігор, вимагає джойстиків з відстеженням позиції. В мене вже були джойстики від Nintendo Switch - на відміну від типових геймпадів, тут маємо окремий контролер для кожної руки. Тому вони підходять і як ВР-контролери. Це вміє програма Driver4VR - вона перетворює різні пристрої під ВР, в тому числі й джойкони з Switch. Працює це не ідеально, бо джойкони знають тільки свою орієнтацію, а розташування розраховується за допомогою інверсної кінематики. Але жити можна.
-
Room-Scale VR. Для повного занурення нам ще не вистачає відстеження в просторі шолома (а краще вже й рук.) Це теж вміє Driver4VR. Причому зараз він взагалі це вміє з вебкамерою, а тоді треба було роздобути Kinect. Kinect то така приставка для XBox, фактично камера, яка розпізнає положення тіла. Для Кінекта ще треба знайти адаптер, щоб підключати його до ПК. Головна проблема Kinect (принаймні першої версії) - це дуже вузьке поле зору. Треба стояти від камери на відстані 2-3 метри. Зате далі все працює надійно, та у грі стає можливо присідати, нахилятися і так далі.
Озброєний таким комплектом, я пограв може з пару годин. Напевно, розвʼязувати цю задачку було цікавіше, ніж користуватись. Не повторюйте це вдома.
07.05.2023
Half-Life: Alyx без ВР
👓 Сьогодні нарешті довелося пограти в Half-Life: Alyx. Специфіка цієї гри в тому, що вона вимагає шолом віртуальної реальності. Я люблю халф-лайф, але не настільки, щоб купувати коштовне залізо. Натомість натрапив на мод HLA-NoVR, який повертає Half-Life: Alyx назад до форми звичайного шутера. І шутер виходить пречудовий.
Одним словом, якщо тобі подобаються шутери, то Half-Life: Alyx з модом HLA-NoVR рекомендую всім серцем. Атмосфера та графіка на висоті. Геймплей не гірше ніж, скажімо, Resident Evil 8 (тобто шутер “з елементами виживання”).
Само собою, елементи, що спираються на віртуальну реальність, в більшій частині втрачені. Не доведеться перезаряджати руками рушницю, копатися у смітті та малювати віртуальним маркером по віртуальній дошці. Взаємодія з простором нагадує ігри серії Amnesia. Деякі головоломки очевидно прибрані за неможливістю. Тож треба признати, що правильний спосіб пережити HL: Alyx - це з шоломом, та нічого його не замінить.
Проте, як виявляється. окрім атракціону з ВР в Alyx міститься й повноцінний шутер. Причому як я уявляю, кращій, ніж у ВР, бо має нормальне WASD переміщення, а не ВР-телепортацію, як можна побачити на цьому відео. Чесно, не можу уявити, щоб телепортація якось покращувала геймплей шутера.
Де гра видає свою природу. Патрони та аптечки на екрані виглядають ну дуже маленькими, та за ними доводиться полювати мишею. Платформінг не ідеальний — бо у ВР з платформи на платформу просто тривіально телепортуєшся, от і не тестували. Так само, зустрічаються місця, де підлога не рівна, а заставлена декораціями, та через колізії по ній доводиться bunny-hopати - у ВР нема вільного переміщення, та цього не помітиш. Але в цілому, якісний захопливий шутер, в який можна грати хоч цілий день, на відміну від ВР.
06.05.2023
Скомбінував глобус та карту
Скомбінував глобус та карту в єдину сцену. Вийшло саме так, як я собі уявляв, хоча анімація поки базова та не вистачає відміток.
Найскладніший аспект всієї цієї задачі — це орієнтація в системах координат. Наприклад, в програмуванні всі звикли, що перша координата (i
) йде вниз, а друга (j
) - ліворуч. Але в графіці перша координата то x
, а y
йде знизу вгору. Коли доводиться генерувати площини та відкладати текстурні координати, то мозок просто ламається. Потім по багато разів передивляєшся код, щоб ніде не було помилок.
Ще — виявилося складним зробити, щоб карта на глобусі відповідала локальній. Якщо в глобусі мало трикутників (наприклад, 2000), то проєкція викривляє текстуру, чого не помітиш, поки не буде потреби “влучити” в точку з точністю до кілометрів. Це вирішується збільшенням кількості трикутників; але в ідеалі, щоб спростити сцену, в міру наближення до точки від глобуса має залишатися дедалі менший шматочок з дедалі більшою деталізацією.
Для того, щоб нормально стилізувати стежку, є клас Line2 - бо стандартна лінія може бути тільки шириною в один піксель. У Three.js багато таких “прикладів”, що часто містять бібліотеку, яку можна використати в власних проєктах.
Нарешті, за допомогою бібліотеки suncalc я визначаю розташування сонця в день походу та емулюю його джерелом світла. Дрібниця, але мені приємно. Та й робиться просто — оскільки карта вже зорієнтована так, що вісь Y вказує на північ, то сонячні азимут та висота збігаються зі стандартними сферичними координатами 𝜑 та 𝜃.