Для вас підготував серію статей про мобільний геймдев, засновану на отриманому досвіді і пройдених граблях. У першій статті мова піде про створення власного кроссплатформенного движку для мобільних ігор. Правду кажучи не тільки мобільних, і не тільки ігор.
Зміст
Частина 1. Мобільний кроссплатформний двигун
Частина 2. Рендеринг UTF-8 тексту за допомогою SDF-шрифту
Частина 3. Рендеринг краплі з прозорістю та відображеннями
А чи потрібен свій движок взагалі?
Щоразу, коли черговий популярний движок стає безкоштовним або відкритим, я ставлю собі це питання. Давайте розглянемо плюси і мінуси:
Плюси
- Ви завжди знаєте як працюють ваші проекти всередині, а головне можете впливати на їх роботу як побажаєте. Вам не потрібно штурмувати форуми розробників проханнями додати потрібний вам функціонал або пофіксити старі баги.
- Ви можете самостійно додавати підтримку нових платформ і додавати нові сторонні SDK.
- Ви зможете використовувати будь-які зручні вам формати зберігання даних (графіка, звуки, ресурси).
- Ви не обмежені жодними ліцензіями.
Мінуси
- Все доведеться писати самому, а так само вникати в усі нюанси кожної платформи. Цей процес займе досить багато часу, тому просто так «заради інтересу» цим займатися не варто. Інша справа, якщо ви займаєтеся геймдевом професійно і плануєте випускати досить багато ігор. Практика показує, що більшість ігрових студій рано чи пізно створюють свої SDK.
- Якщо ви робите проекти на замовлення, то не всі замовники раді вашим самописним рішенням. Адже можливо підтримувати проект доведеться зовсім іншим людям.
- У багатьох популярних рушіях є вбудовані візуальні 2D/3D редактори. Про їх зручність можна довго сперечатися, але у вас спочатку не буде і цього.
Звичайно кожен для себе побачить свої плюси і мінуси. Моя справа попередити. Поїхали!
З чого це зроблено?
Ми говоримо в першу чергу про розробку мобільних ігор, тому основа буде однозначно на C + +/OpenGL. Без варіантів! Однак без другорядних мов теж не обійтися. Давайте подивимося що використовується на кожній платформі:
Як бачите C++ і OpenGL зустрічаються всюди. На ObjectceC/Java/C # доведеться написати тільки обгортку для роботи з системою девайса. Сам же код ваших проектів буде єдиний - на С++. На цій ноті скажемо: «До побачення, болісне портування!».
OpenGL
Рекомендую використовувати OpenGL 2.0 і вище. Час OpenGL 1.1 давно минув, а перехід з 1.х на 2.х ви будете згадувати в кошмарних снах. Однак не поспішайте використовувати останню версію OpenGL не переконавшись, що всі цільові платформи його підтримують. У більшості випадків OpenGL 2.0 цілком вистачає і підтримують його всі платформи.
З++
Та ж ситуація і з С++ 11/14. Якщо впевнені, що всі компілятори з ним дружать - супер. Мені ж вистачає C++ 98, так що при додаванні нової платформи - а в планах є підтримка консолей - я буду спокійний.
IDE
Xcode - для iOS, OSX, tvOS. Плагіни через CocoaPods.
Android Studio – для Android. Плагіни через Gradle.
Visual Studio - все що під Windows.
Структура рушія
Насамперед рушій і проекти повинні акуратно і логічно зберігатися на диску. У підсумку я прийшов до такої структури:
- Engine (все що стосується рушія)
- Classes (.h, .cpp файли рушія)
- Modules (модулі і сторонні SDK, які потрібні не у всіх проектах)
- Рекламні SDK
- Аналітика
- Game Center
- Зображення
- Соціальні сітки
- … тощо.
- Platforms (специфічні класи по платформах)
- Android
- iOS
- OSX
- tvOS
- … інші платформи
- Тестовий проект
- iOS
- Проект.xcworkspace
- Icons (іконки програми, * auto - збирач проекту сам заповнює ці теки)
- Launch (картинки при старті програми, * auto)
- Res (готові ресурси програми, * auto)
- Pods
- … інші файли ios проекту, plist, build тощо.
- Android, OSX, tvOS… такі ж за змістом теки під різні платформи і IDE. Для Android Studio своя структура проекту.
- Assets
- Icons (іконки програми всіх розмірів)
- Launch (ланч-скріни всіх розмірів)
- Resources (оригінали ресурсів проекту)
- General (основні ресурси для всіх платформ)
- Lang (шрифти і локалізація)
- Fonts (тека з SDF)
- xls (файл з перекладами)
- Platform (ресурси специфічні для платформи)
- iOS
- Android
- … інші платформи
- Shaders (шейдери)
- Sounds (звуки)
- MP3 (для треків)
- OGG (для звуків)
- Textures (ресурси за форматами текстур)
- ATI
- ETC
- PVRTC
- S3TC
- Source (.h, .cpp файли самого проекту)
- Config (файл параметрів проекту для збирача)
- iOS
Збірник проекту
Збирач проекту відповідає за підготовку ресурсів, формати і упаковку. А саме:
- Бере іконки (або навіть одну іконку максимального розміру 1024х1024) з Assets/Icons, робить інші розміри (від 16х16 до 1024х1024) і копіює в теки по платформах [Platform ]/Icons
- Так само робить з екранами старту з Assets/Launch
- Бере ресурси програми з наступних тек:
- Resources/General
- Resources/Shaders
- Resources/Sounds/MP3, OGG
- Resources/Textures/[ потрібний формат текстур]
- Resources/Platform/[ платформа]
- Resources/Lang/Fonts
Далі збирач конвертує ресурси, шифрує, запаковує і поміщає у [Platform ]/Res.
Найважливіше тут - це конвертація файлів за розширенням. Я використовую такі конвертації:
- PNG і JPEG перетворюються на WEBP. Загальні параметри конвертації (наприклад, мінімальну якість) можна винести в налаштування проекту Project/Config, а можна і вказати прямо в назві файла.
Наприклад, image {q100.png буде стиснута з параметром quality 100, а image ауд less.png буде стиснута без втрати якості.
Так само добре себе зарекомендували пресети.
Наприклад до image ауд p1.png буде застосований 1й пресет, який переверне картинку дзеркально і збереже з якістю 90%.
- Текстові файли та шейдери (.txt, .vs, .ps) шифруються нехитрим способом. Простий захист від цікавих.
- Файл локалізації Resources/Lang/Lang.xls парситься за мовами, шифрується і упаковується в бінарний формат.
- На літі створюються текстурні атласи. Наприклад, з теки з назвою folder ауд atlas будуть взяті всі зображення і упаковані в єдину картинку + збережеться файлик з координатами.
- Звуки перетворюються у формат OGG.
- 3D моделі конвертуються у внутрішній формат рушія.
- Файли з іменем file.pack перетворюються з текстових на бінарні. Це добре підходить для всіляких конфігів гри, рівнів тощо.
При цьому збирач дивиться час зміни файлу і конвертує лише змінені файли, що помітно прискорює його роботу. Конкретно у мене збирач написаний на PHP. Можливо це не найкращий вибір, але мені так було простіше. До того ж потенційно його можна перенести на сервер для командної роботи.
Формати
Я б рекомендував використовувати такі формати:
WEBP для картинок. Навряд чи для кого-небудь цей формат виявиться новим. А для тих, хто чує про нього вперше - webp може зберігати картинку без втрати якості як PNG, а так само з втратою - як JPEG, однак з помітно кращою якістю, меншою вагою і з прозорістю. Ще з плюсів - можливість скейлу картинки на льоту при читанні файлу. Компілюється libwebp під всі платформи без проблем.
OGG для звуків. Андроїд нативно розуміє OGG формат, а на iOS/OSX/tvOS я використовую бібліотеку Tremor (fixed-point version of the Ogg Vorbis) для розкодування звуків у WAV і згодовування їх OpenAL. Спроби використовувати OpenAL і на андроїді успіхом не увінчалися (звуки були із затримками).
Класи і додатки
Розберемо детальніше які класи містить движок і для чого потрібні модулі?
Правило «що виносити в модуль, а що в движок?» дуже просте:
Дотримуючись цього правила, я розподілив класи наступним чином:
Рушій
- Робота з платформою. Тут відбувається ініціалізація програми, а також передача зовнішніх подій (пауза, тачскрін, кнопки) в основний клас движка.
- Основний клас. Тут крутиться mainloop, обробляються вхідні події (вже в універсальному вигляді незалежному від платформи), відбувається управління потоками і фоновими завданнями.
- Робота з 2D. Вивід картинок, атласів, постефектів.
- Робота з 3D-моделями. Завантаження моделей, рендеринг, керування шейдерами.
- Стандартні елементи UI. Вікна, кнопки, скролінг, сповіщення.
- Текстури. Завантаження і вивантаження текстур. Самі декодери знаходяться в модулях.
- Вивід тексту, рендеринг SDF-шрифтів.
- Математика. Всілякі формули, матриці, кватерніони тощо.
- Соціалка. Надсилання листів, стандартний шаринг, rate me. Самі ж соц. мережі винесені в модулі.
- Читання/запис файлів.
- Робота з UTF8 рядками.
- Робота з мережею.
- Музика/звуки.
Додатки
- Соціалка
- Google Plus
- VK
- Replay Kit (запис екрана для iOS)
- JSON/XML
- Декодери картинок
- WEBP
- JPEG
- PNG
- In-apps (внутрішні платежі)
- Game Center, Google Play Services
- Crashlytics (відстежувати краші)
- Branch (глибокі посилання)
- Аналітика
- Google Analytics
- Game Analytics
- Flurry
- Реклама
- Appodeal (UPD недобросовісна компанія)
- Chartboost
- Fyber
- AdColony
- UnityAds
- Tapjoy
- Google Ads
- Heyzap
- AdToApp
У наступних статтях я докладніше зупинюся на певних класах і модулях, з прикладами і корисностями. Окрему увагу хочу приділити рендерінгу SDF шрифтів (Signed Distance Field) і шейдерам у грі з шапки.
