Я зробив FPV-дрон у GTA San Andreas з реальною фізикою і керуванням з апаратури
Звідки взагалі взялася ідея запхати дрон в гру
Нещодавно мене прорвало: купив нормальний пульт, налітав годин 50 в Liftoff (це fpv симулятор, якщо хтось не в темі). І якось одного вечора дрони, SAMP і ностальгія за GTA зійшлися в один пазл. Залишалися невикористані ліміти в клоді та жорстка потреба в дофаміні (ахаха). Та й я сів кодити, правда я ще не знав який капець мене чекає, а шо робить :)
Перше, що я накидав — базову фізику: масу, тягу, розкрутку моторів, аеродинамічний опір. Все працює, дрон летить. А от камера — фіг. Тобто коптер нахиляється, а картинка на екрані залишається пласкою, ніби камеру прикрутили шурупами до горизонту. Літати було нереально, бо іменно крен камери дає те саме відчуття FPV-польоту. Без нього це просто якийсь патик з об’єктивом.
Почав копати. Спочатку спробував писати напряму в CCamera.mCameraMatrix кожен кадр. Без толку. Потім попробував залізти ще глибше, в низькорівневу RwCamera.matrix. А це вже була рулетка, бо кривий вказівник міг легко покласти весь процес гри. І він його поклав. Ну і попробував нативну функція attachCameraToVehicle, яка працює для вигляду ззовні, але зовсім не підходить для першої особи.
І тут я випадково зрозумів, чому перші два варіанти були безтолкові. Хук onD3DPresent, де я все це редагував, викликається ПІСЛЯ того, як кадр уже відрендерено. Тобто я оновлював дані для кадру, який вже на екрані, кароче запізнювався.
Ну і на цій спробі я вже майже здався. Ну й з трудом нагуглив якийсь на старий скрипт з бородатого форуму, де чувак просто телепортував гравця всередину об’єкта і вмикав стандартну ігрову камеру «в транспорті». Реально воно звучить як костиль поверх костиля. Але коли нічо не працює, то і вони — норм варіант. І це зразу спрацювало. Та сама камера, яка кренить вертольотік у ванільній GTA, ідеально кренить дрон, бо для двіжка це просто ще одна машинка. Робочим виявився той єдиний варіант, який взагалі не чіпав камеру))
Другий баг випив мені не менше крові. Дрон класно літав, аж поки не наближався до землі або якогось даху на пару метрів. Тоді його різко смикало вниз. Перша думка: колізії глючать. Я перебрав і повимикав усі колізійні тогли, які тільки знайшов, перетестив купу прапорців CVehicle по одному. Нічо не мінялося.
Та й як завжди, діло було взагалі не в колізіях. Нативна функція setCarCoordinates(), яку я смикав щокадру для оновлення позиції, має під капотом логіку тіпа «не дай транспорту провалитися під текстуру». Вона сама шукає найближчу поверхню і підтягує туди координати. І коли ти викликаєш її 60 разів на секунду біля даху, вона старається тебе на той довбаний дах посадити.
Та й тут фікс вийшов простим, писати позицію безпосередньо в матрицю дрона, ігноруючи цю натівку. Баг, на пошук якого пішла купа часу, пропав після видалення одного виклику функції, кароче база.
Після тих затиків решта пішла значно легше.
По фізиці вийшло таке: Маса, тяга, опір повітря, граунд-ефект (коли дрон відштовхується повітрям від предметів), три режими польоту як на справжньому дроні (ACRO, LEVEL, HORIZON) плюс двонаправлений 3D-газ і арм/дісарм-тумблер.
Можна керувати з любого підключеного контролера: реальний пульт чи звичайний геймпад, обирається прям в меню, і можна навіть літати одночасно в SAMP і синглплеєрі з одного пульта, демон роздає сигнал на кілька девайсів одночасно.
Зробив рекордер польотів з відтворенням у стилі відеоплеєра і пару силів OSD.
І над всім цим крутезне меню налаштувань, яке я в якийсь момент почав робити красіво: напівпрозоре вікно, док знизу як у macOS, пошук по настройках, мастер першого запуску з калібруванням стіків і графічним підбором мертвих зон, пару пресетів дронів.
Профілі, до речі, можна шарити: дублюєш будь-який, тюниш під себе, тиснеш «поділитись» — вилазить текст, копіюєш і кидаєш комусь, той вставляє собі й натискає застосувати. Якщо хтось зробить класний конфіг — скидайте :)
Доречі, реверс структур пам’яті гри і аналіз байткоду, я взагалі вперше в житті роблю. І навіть коли раніше писав щось подібне до low-level штук, це було здебільшого викликати готові модулі. І знаєте в чому був головний кайф? Не в тому, що AI написав купу коду за мене, а в тому, наскільки глибоко і швидко можна залізти в незнайому технологію, просто через промпти. А це ж довелось би копатися в дебагерах якигось щоб розібратися як працює та чи інша функція...
Ну насправді найважче тут не код був, а просто мати терпіння доробити ту штуку до кінця, розібратися з прихованими поведінками функцій, розібратися чому камера не рухається через запис кутів в матрицю об’єкта камери. Але воно того вартувало, зараз літаю під мостом на грув, розношу поліцію з 3 зірочками розшуку, а вони бідні не можуть навіть по мені попасти, шось там бігають, суєтяться.
Код і повний setup-гайд тут: github.com/invilso/gta-fpv-drone, а тут Відеоогляд. Є інсталятор під Linux і Windows, перевіряє залежності, каже чого не вистачає і де взяти. Писав і літав я на Linux+Proton. Крос-платформні граблі ніби врахував, але на Windows не ганяв. Якщо хтось затестить — маякніть, чи все завелося.
1 коментар
Додати коментар Підписатись на коментаріВідписатись від коментарівДуже круто!