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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читайте також  Як включити клавішу F8 для входу в безпечний режим Windows 10

Проблема з 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++, в іншому — шейдер. Завдання в тому, щоб забити його працювати.

Читайте також  Як дізнатися збірку Windows 10 на комп'ютері, в образі або на флешці

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

Готовий результат лежить ось тут 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
);

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

Читайте також  Ревізія рівнів доступу користувачів за допомогою Power BI на прикладі CMS Бітрікс (БУС)

 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 адреса не оприлюднюватиметься. Обов’язкові поля позначені *