Намагаємося налаштувати середовище для розробки гри під Windows

Тільки що прийшла в голову думка — потрібно знайти якесь хобі. Інакше з глузду можна з’їхати. А оскільки я дуже марний людина, нічого крім як тикати кнопки не вміє, хобі буде таке: не рідше одного разу на тиждень влаштовувати стрім з написанням іграшки. Після стріму запис публікується на Хабре. (Можна спробувати постити на Хабр прям лайв, але це значно складніше).

Написання дуже feedback driven — якщо комусь потрібні пояснення, то я можу пояснити як зможу. Якщо є пропозиції — постараюся враховувати. На хабре читаються всі коментарі до останнього, в інших місцях — як вийде.

Перший млинець грудкою ось тут:

Під катом — тезисний опис для тих, кому справедливо влом витрачати на перегляд півтори години.

Напрямні ідеї

Перший цікавий аспект у тому, що хочеться написати все без хрюмворков. Як звичайний джавист робить? Виникла проблема — гатиш залежно хрюмворк, і він тобі вирішує питання. Ціна цього — з-за такого свинства проект перетворюється на свинарник, і ніхто не може в точності визначити, що ж відбувається. Хочеться спробувати написати без цієї свиноферми, чистенько і акуратно. Можливо, це неможливо — ласка, повідомте в коментарях.

Другий аспет. Я все життя кодил на Java та PHP. Був досвід розробки іграшок, але тільки серверної частини з відповіддю по мережі, і жодного разу — цього десктопного програми на C++. Тому, по суті це буде шоу виродків — людина не розбирається в питанні спробує якось своїми словами описати, що відбувається.

Ні, ніякого практичного значення це не має. Це щоб не з’їхати з глузду, і щоб мотивувати дорослих бородатих дядьків теж взятися за клавіатуру і запив яку-небудь іграшку.

Рутина наносить удар в п’ятак

На жаль, програмування ніколи не починається з легкого і приємного розваги. Спочатку відбувається період хворобливого копання у налаштуваннях середовища і IDE.

Перше, що я зрозумів щодо Visual Studio — це відмінний інструмент для професіонала, але на новачка він справляє дуже фрустрирующее враження. Після Eclipse і IntelliJ IDEA все, знаєте, якесь неприродне, сиреневенький бесперспективняк з переподвыподвертом. Справа не в якому разі не VS, справа в мені 🙂

І з плагінами постійно якась біда.

Тому вольовим рішенням відмовляємося від Вижуалки і дивимося, що ще є. Vim, Emacs і інші редактори, не розуміють структури оригіналу — відправляються лісом. Перша ж спроба використовувати Eclipse провалилася, тому інструментом був обраний CLion.

Читайте також  За півроку польоту на Марс астронавти отримають більше шкоди, ніж за всю кар'єру

Проблема з CLion в тому, що він не все ще не вміє повноцінно працювати з компілятором Visual Studio. Якщо спробувати зробити що-небудь в ньому, то буде ось таке:

Звичайно, тут би в тред набігти гошникам і почати кричати надривним голосом, що налагоджувальних принтів всіх вистачить. Але ми їх слухати, звичайно, не станемо.

Тому потрібно те, що CLion вміє добре, і це MinGW.

Вибираємо MinGW

Є велика таблиця версій.

І по ній видно, що має сенс дивитися тільки на Cygwin і Msys2. Msys2 якийсь дивний — у нього мало коммитеров, пакети лежать на особистому гітхабі одного з авторів. З іншого боку, він дійсно кльовий — там свіжий компілятор і купа пакетів. Це має вирішальне значення.

Установка полягає в прокликивании next-next-ok, і потім багаторазовому виконанні команди оновлення (pacman -Syu, як в Арчлинуксе) з перезапуском терміналу Msys2, поки він не скаже, що все вийшло в кращому вигляді.

Якщо просто встановити Msys2 по інструкції і спробувати додати його в CLion, не знайдено жодного тулчейна. Його потрібно поставити самостійно, це робиться командою pacman -S mingw-w64-x86_64-toolchain.

Після установки цього пакета, CLion запускає helloworld (який генерується автоматично при створенні нового проекту) і в ньому працює налагодження.

Перевірка можливості #1: просте вікно

По-перше, хочеться зрозуміти, запуститься чи взагалі хоч якесь десктопное додаток. Все-таки, це не рідний PlatformSDK, а MinGW.

Для цього підійде нехитра прога, малює вікно з допомогою винапи.

І так, з MinGW вона запускається. А ось з тулчейном Visual Studio воно сипле якимись помилками, але з ними розбиратися я не став, тому що — а навіщо, якщо у нас вже працює цільова платформа?

Перевірка можливості #2: трикутник з шейдером

Зрозуміло, що для написання чогось життєздатного недостатньо виводити пікселі на вікні. Це гальмівно, незручно, немає ніяких модних штучок. Коротше, нам потрібен DirectX.

Ключове питання про CLion+MinGW — саме це. Якщо вони не зможуть юзати DirectX, відправляються на смітник.

Для тестування був нагуглен дуже короткий туторіал, який складається всього з двох файлів: в одному весь код на C++, в іншому — шейдер. Завдання в тому, щоб забити його працювати.

Читайте також  Творити дичину на нічному хакатоне

Крім однофайловости цей туторіал дуже хороший тим, що там на пальцях розповідається, як він працює. Можливо, цю статтю варто перевсти на Хабр (напишіть в коментарях).

Готовий результат лежить ось тут GitHub. Тут опишу, які проблеми зустрілися.

Дрібниці і сміття

Багато L-рядків стали просто рядками. Можна повидаляти букви L. У багатьох місцях потрібно замінити NULL на 0, щоб не падало.

Незважаючи на те, що використовувався set(CMAKE_CXX_STANDARD 17), цьому плані нічого цікавого не сталося взагалі, нічого не розвалилося.

Заголовки і либы

Справа, звичайно, в тому, що цей приклад — дуже древній, написаний у часи задовго до Windows 10. DirectX тепер не знаходиться в окремому DirectX SDK як у часи нашої неоднозначною молодості, а засунуть прямо в Windows SDK.

Тому перше, що потрібно зробити — запустити програму Visual Studio і перевірити, що встановлена найсвіжіша версія Windows SDK.

Друге питання — в заголовках.

#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>

Їх більше немає, потрібно щось на кшталт:

#include <d3d9.h>
#include <d3d10.h>
#include <d3d11.h>
#include <dxgi.h>

І потім в CMakeLists додати пошук до них в кінець файлу:

set(LIBS d3d9 d3d11 d3dcompiler_43)
target_link_libraries(src ${LIBS})

Відсутні API

Раніше була ось така структура:

typedef struct D3DXCOLOR {
 FLOAT r;
 FLOAT g;
 FLOAT b;
 FLOAT a;
} D3DXCOLOR, *LPD3DXCOLOR;

І більше її немає. Втім, у всіх місцях, де вона реально була потрібна, вийшло замінити D3DXCOLOR(0.0 f, 0.2 f, 0.4 f, 1.0 f) на {0.0 f, 0.2 f, 0.4 f, 1.0 f}.

Проблема цікавішою виявилася з D3DX11CompileFromFile. Її більше немає!

У статті Living without D3DX її запропонували замінити на D3DCompileFromFile.

Але от проблемка, D3DCompileFromFile у нас теж чомусь недоступне!

Невелике розслідування показало, що документація Microsoft пропонує скористатися новою версією API:

А MinGW відправляє нас в минуле на кілька років:

Втім, у 32-бітної версії є більш новий заголовок, але як його присобачити до 64-біт я не розібрався. 32 біта на, напевно, на фіг не здалися.

З одного боку, це дуже сумно, тому що віщує гемор у відносинах з MinGW надалі. Цікаво, хто мантейнеры всіх цих справ.

З іншого боку, якщо взяти відсутню D3DCompile і присутню D3DCompileFromFile:

HRESULT WINAPI D3DCompileFromFile(
 in LPCWSTR pFileName,
 in_opt const D3D_SHADER_MACRO pDefines,
 in_opt ID3DInclude pInclude,
 in LPCSTR pEntrypoint,
 in LPCSTR pTarget,
 in UINT Flags1,
 in UINT Flags2,
 out ID3DBlob ppCode,
 out_opt ID3DBlob ppErrorMsgs
);

HRESULT WINAPI D3DCompile(
 in LPCVOID pSrcData,
 in SIZE_T SrcDataSize,
 in_opt LPCSTR pSourceName,
 in_opt const D3D_SHADER_MACRO pDefines,
 in_opt ID3DInclude pInclude,
 in_opt LPCSTR pEntrypoint,
 in LPCSTR pTarget,
 in UINT Flags1,
 in UINT Flags2,
 out ID3DBlob ppCode,
 out_opt ID3DBlob ppErrorMsgs
);

то виявиться, що там різниця тільки в наступному:

Читайте також  Як підключити принтер до ноутбука - інструкція

 in LPCWSTR pFileName,

проти

 in LPCVOID pSrcData,
 in SIZE_T SrcDataSize,
 in_opt LPCSTR pSourceName,

На жаль, я не знаю C++, тому наговнокодил як умів: просто додав вичитування файлу і редирект цих даних в D3DCompile.

void WINAPI D3DCompileFromFile(const char *filename,
 const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
 const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages) {

 SIZE_T data_size;
 char* buffer;

 ifstream infile;
 infile.open(filename, ios::binary);
 infile.seekg(0, ios::end);
 data_size = infile.tellg();
 infile.seekg(0, ios::beg);
 buffer = new char[data_size];
 infile.read(buffer, data_size);
infile.close();

 D3DCompile(buffer, data_size,filename,
 defines, include,entrypoint,
 target, sflags, eflags, shader, error_messages);
}

Єдине важливе розходження між померлим в пітьмі століть D3DX11CompileFromFile і нашим саморобний D3DCompileFromFile — у відсутності в новому API ID3DX11ThreadPump в якості параметра. Це щось для асинхонности, можливо якийсь тредпул? Втім, в туториале він і не використовувався, там на його місці стоїть 0.

Підсумки

Зв’язка DirectX + MinGW + Msys2 + CLion є достатньо життєздатною, щоб запилити просту гру. Є можливість не тільки використовувати базове винапи, але і малювати, і навіть з шейдерами.

Загалом-то, все. Нагадую, що нехитрий результат лежить на GitHub.

Будь ласка, пам’ятайте, що це не мій код, а модифікований текст з туториала — втім я сподіваюся, що таке його використання є чесним та цільовим. Але тим не менш, саме тому там немає нікою нормальної ліцензії.

Фідбек

Будь ласка, пишіть в коментарях ваші зауваження та пропозиції. Заради цього все і робиться, послухати, що скажете ви. Особливо якщо ви — досвідчений игропрограммист, прямо зубр, бізон, і не поміщаєшся в тред за розмірами. Обов’язково найдо зайти і що-небудь написати.

Нагадую, що я, як і будь-другого блогер, харчуюся лайками і дизайками. Чим лютіше ви будете телефонувати стрілку вгору під цим постом, тим більш імовірно вийде наступний пост і стрім.

олег народився в інтернеті
в поважній геймерської сім'ї
харчувався лайками і в гугол
за двійки ставили його

© Олександр Раєвський

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

You may also like...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *