Moai SDK 1.5 - багатоплатформовий 2д ігровий движок


Сьогодні я хочу розповісти про один маловідомий ігровому движку, який ми використовуємо вже рік для кроссплатформенной розробки мобільних ігор. Для 2д він нас повністю влаштовує, а єдиним конкурентом може бути тільки Unity3d через свого редактора. Відсутність належної уваги до MOAI SDK , очевидно, пов'язано з високим порогом входу — самі розробники (Zipline Games) позиціонують свій продукт як «The mobile platform for pro game developers», хоча розібравшись з установкою і налаштуванням оточення можна дуже швидко і просто клепати гри на Lua.
 
 Чим же мені так сподобався MOAI:
 
     
  • Движок написаний на C + +, ігрова логіка пишеться на Lua. Є підтримка luajit (на iOS тільки в режимі інтерпретатора)
  •  
  • Відкритий вихідний код. Ліцензія CPAL — необхідно вказувати логотип, назву, авторів і посилання на MOAI на завантажувальному екрані або в титрах
  •  
  • кроссплатформенную: Windows, Mac OS X, Linux, iOS, Android, OUYA, а також є експерименти з html5 через emscripten. Розробка підтримується на Windows, Mac OS X і Linux. Для складання під iOS потрібен Mac. Теоретично, додати нову платформу не складно — треба написати «хост», який створить OpenGL контекст і буде викликати методи обробки введення
  •  
  • Lua API дуже низькорівневий. Це і плюс, і мінус. Для ефективної розробки просто необхідний Lua фреймворк більш високого рівня
  •  
  • Усередині використовуються круті алгоритми і технології. Рендерер з автоматичним батчінгом (cocos2d начебто теж цього навчився). Action tree — все що періодично оновлюється (анімації, фізика) представлено у вигляді дерева, батьківські вузли передають минулий час (дельту) своїм дітям; це дозволяє вибудовувати ієрархію анімацій, зупиняти і продовжувати їх разом, міняти швидкість відтворення
  •  
  • Немає звичного графа сцени як в інших 2д движках. Для обробки залежностей використовується dependency graph. У об'єктів є безліч атрибутів (координата, колір, шейдер, ...) — можна задавати залежності між ними, наприклад, прив'язати поворот одного спрайта до координати Х іншого. Движок виробляє розрахунок тільки змінених атрибутів, що по ідеї зменшує витрати на оновлення. По факту це схоже на нодів архітектуру Maya, Nuke, матеріалів з UE — прив'язуй що хочеш до чого хочеш, аби тип збігався. Є спеціальний ScriptNode якого можна додавати свої атрибути і задавати коллбек на їх обробку
  •  
  • Кілька класів для роботи з тайлмапамі. Hex, diamond, rectangular сітки, пошук шляху
  •  
  • Є підтримка 3д — тобто все трансформи і об'єкти по суті своїй 3д
  •  
 
 Мінуси і недоробки:
 
     
  • Прогалини в документації, приклади часто неробочі. Нечисленне співтовариство
  •  
  • Для збирання використовується Cmake. Тут немає однієї кнопки «зібрати під ...» як у Юніті або Короні, часто доводиться боротися з помилками компілятора і линкера
  •  
  • Lua api не повний. Наприклад, часто немає балансу між сетерами і геттеров (сеттерів більше). Тому корисно розбиратися в написанні Біндінг і розширювати їх при необхідності
  •  
  • Ні редактора
  •  
  • Вбудований звуковий движок UNTZ дуже примітивний. Є Біндінг до fmod, але швидше за все вони сильно застаріли, тому що ними ніби як ніхто не користується
  •  
  • Мабуть, з монетизацією фреймворка у розробників не склалося — робити платним і закритим його категорично не хочеться, а MOAI Cloud не виправдав себе. На всяку нісенітницю типу впорядкування документації і прикладів у Zipline Games немає ні часу, ні мотивації, все в основному робиться співтовариством. Це не означає що MOAI SKD мертвий, немає, Zipline Games використовують MOAI для внутрішніх проектів, розвиток триває (ось зовсім недавно з'явилася підтримка векторних примітивів через libtess, в процесі розробки власний движок для обробки простих зіткнень, щоб не тягнути цілком box2d або chipmunk)
  •  
 
 

Установка (Mac OS X)

Опишу установку тільки на OS X, т.к. не маю під рукою windows системи.
 
Клонуємо офіційний репозиторій:
 
git clone https://github.com/moai/moai-dev.git

Запускаємо скрипт, який збере хост під нашу систему:
 
cd moai-dev
bin/build-osx-sdl.sh 

Сподіваюся все пройде без помилок, тоді виконуваний файл стане доступний в release / osx / host-sdl / bin / moai, зробимо на нього лінк (~ / bin у мене доданий в PATH):
 
ln -s /Users/vavius/moai-dev/release/osx/host-sdl/bin/moai ~/bin/moai

Запускаємо приклад, переконуємося що все працює:
 
cd samples/hello-moai
moai

Бачимо що крутиться фіговіна і вітає текст:
 
 
 

Пишемо на Lua

Почнемо з мінімального прикладу — намалюємо квадратний спрайт по центру екрану:
 
 Код:
 
-- 1
MOAISim.openWindow ( "sample", 600, 240 )

local viewport = MOAIViewport.new ()
viewport:setSize ( 600, 240 )
viewport:setScale ( 600, 240 )

-- 2
local layer = MOAILayer.new ()
layer:setViewport ( viewport )

-- 3
local renderTable = { layer }
MOAIGfxDevice.getFrameBuffer ():setRenderTable ( renderTable )

-- 4
local deck = MOAIGfxQuad2D.new ()
deck:setTexture ( "moai.png" )
deck:setRect ( -64, -64, 64, 64 )

-- 5
local prop = MOAIProp.new ()
prop:setDeck ( deck )

layer:insertProp ( prop )

 Опис відбувається по пунктах:
 
     
  1. Створюємо вікно і вьюпорті. Вьюпорті дозволяє працювати в логічних координатах, не прив'язуючись до пікселів
  2.  
  3. Шар — це контейнер для пропилу (а пропити називається все що може бути намальовано). Шару можна задати камеру, при цьому будуть рендери тільки ті пропити, які потрапляють в поточний вьюпорті. Шар отвественность за сортування (порядок рендеринга) — є безліч варіантів, по координаті X, Y, Z окремо або по вектору, за пріоритетом (ціле число), а також спеціальний вид ISO_SORT для ізометричних тайлових ігор. У кожного шару є контейнер MOAIPartition для оптимізацій просторових запитів — хіт тіста і raycast'ов, всередині використовується багаторівнева сітка
  4.  
  5. Задаємо рендер таблицю — список renderable об'єктів, які будуть отрісовани під фреймбуфер по порядку. Шар при рендере малює все додані до нього пропив. Таблиця може містити вкладені таблиці, що дуже зручно для створення менеджера сцен
  6.  
  7. Deck — об'єкт, що визначає візуальну частину. Він зберігає геометрію (в даному випадку квад — два трикутника), UV координати, посилання на текстуру і шейдер
  8.  
  9. Prop — збірний образ об'єкта, який малюється на екрані. Це в принципі не обов'язково один окремий спрайт, а також може бути і 3д меш і тайловая карта залежно від встановленої деки
  10.  
Відразу впадає в очі, що аж надто багато рядків потрібно для здавалося б простої задачі намалювати спрайт. Найчастіше це робиться в одну строчку, а тут треба як мінімум шість. Тому, API надається движком не використовується «як є», а багато пишуть свої обгортки на Lua. У С + + частини MOAI SDK відсутні багато звичні речі такі як: кеш текстур, завантаження спрайтів з атласів, менеджер сцен і переходів між ними, всякі кнопки та інші гуї елементи. Все це пропонується реалізувати на Lua. На загальній продуктивності це врядли сильно позначиться, оскільки більшість операцій виконуються тільки при інінціалізаціі сцени. Звичайно, треба підходити з розумом до написання коду, що не плодити зайвих таблиць, використовувати старі об'єкти, кешувати що можна.
 
 

Повна свобода

Припустимо, не хочемо квадратний квад, а хочемо трапецію, замість setRect використовуємо setQuad:
 
local deck = MOAIGfxQuad2D.new ()
deck:setTexture ( "moai.png" )
deck:setQuad ( 
    -64, 64, 
    64, 64, 
    100, -64,
    -100, -64 )  -- координаты вершин с левого верхнего угла по часовой стрелке

Ось що вийде:
 
 
Замость фон цілком нашої картинкою. Можна використовувати GL_REPEAT на текстурі, але він працює тільки для розмірів кратних ступенями двійки, і картинку з атласу не вийде використовувати. Тому скористаємося класом MOAIGrid:
 
local deck = MOAIGfxQuad2D.new ()
deck:setTexture ( "moai.png" )
deck:setRect ( -0.5, -0.5, 0.5, 0.5 )

local grid = MOAIGrid.new ()
grid:initRectGrid ( 1, 1, 128, 128 )
grid:fill ( 1 )
grid:setRepeat ( true, true )

local prop = MOAIProp.new ()
prop:setDeck ( deck )
prop:setGrid ( grid )

layer:insertProp ( prop )

MOAIGrid потрібен для роботи з тайлами, тут ми инициализируем карту з одного тайла розміром 128x128. Потім ставимо йому індекс 1 методом fill. Деякі типи грудня підтримують індексацію, наприклад MOAIGfxQuadDeck2D дозволяє задавати багато пар вершинних і UV координат для однієї текстури, що використовується для представлення спрайтові атласу. В даному випадку в нашій деці є тільки один єдиний індекс 1. Включаємо повторення і вказуємо пропу, що слід використовувати сітку для візуалізації.
 
 
На цьому етапі дуже просто зробити анімований прокручується фон. Додаємо одну сходинку в кінець:
 
prop:moveLoc ( -128, 0, 0, 4, MOAIEaseType.LINEAR ):setMode ( MOAITimer.LOOP )

Просто в циклі рухаємо наш проп на ширину одного тайла, а движок сам підставляє відсутні шматки щоб замостити весь екран:
 
 
 

Анімація і Action tree

Переміщення і обертання об'єктів, а також установка режимів програвання анімацій:
 
local move = prop:moveLoc ( 200, 0, 0, 2 )                      -- двигаем
local rot = prop:moveRot ( 0, 0, 360, 2, MOAIEaseType.LINEAR )  -- крутим вокруг оси Z

move:setMode ( MOAITimer.PING_PONG )    -- вперед-назад
rot:setMode ( MOAITimer.LOOP )          -- цикл

 
За замовчуванням анімації додаються до кореня action tree. Але можна їх групувати:
 
local action = MOAIAction.new ()
action:addChild ( move )
action:addChild ( rot )

action:start ()
action:throttle ( 0.5 )

Тепер ми можемо зупиняти і запускати відразу обидві анімації, а за допомогою throttle задавати швидкість відтворення.
 
Послідовність дій реалізується через Lua корутіни. MOAI надає клас MOAICoroutine, успадкований від MOAIAction, що дозволяє додавати корутіни в action tree. Функція blockOnAction викликає yield поки стрілялки не закінчиться.
 
Рухаємо картинку вправо-вліво, а при досягненні крайніх точок робимо один повний оборот:
 
local function func ()
    local distance = 200
    while true do
        local action1 = prop:moveLoc ( distance, 0, 0, 2 )
        MOAICoroutine.blockOnAction ( action1 )

        local action2 = prop:moveRot ( 0, 0, 360, 2 )
        MOAICoroutine.blockOnAction ( action2 )

        distance = -distance
    end
end

local thread = MOAICoroutine.new ()
thread:run ( func )

 
 
 
 

Висновок

У статті розглянуті зовсім примітивні приклади — моєю метою було показати деякі аспекти Lua API, а саме його Низькорівневий і модульність. MOAI SDK намагається не приймати за нас ніяких рішень, не примушує все робити якимось одним загальновизнаним способом, а залишає повну свободу. Звичайно ж спільнота вже реалізувало кілька високорівневих обгорток на чистому Lua, з кешуванням текстур, гуї елементами, менеджером сцен і т.д.
 
Я б не радив використовувати MOAI SDK в продакшені без знання С + +, нюансів складання під обрану платформу і готовності щось змінювати всередині. Практично кожен, хто використовує MOAI SDK має свій форк, який трохи відрізняється від головної гілки. Історично це пов'язано з тим, що у Zipline Games не було часу Мержа пулл-реквести. Однак, зараз деякі члени співтовариства отримали доступ до офіційного репозиторию і розробка пішла бадьоріше.
 
Завдяки відкритості ми змогли реалізувати live reload коду і ресурсів прямо на девайс. Зараз я потихеньку пилю редактор, за образом і подобою Unity3d. Хоча справи пішли повільніше після заробив live reload'a — його вистачає з головою для неймовірного прискорення розробки. Інтерфейси збираємо у векторному редакторі і екпорт відразу в код (декларативного виду, ось приклад: gist.github.com/Vavius/9868572 ). Звичайно, все це можна було приробити до будь-якого движку, до cocos2d-x взагалі без проблем, до Корони посложней, але теж реально. Вобщем, для 2д ігор пересіли ми з кокоса на MOAI і анітрохи не шкодуємо, тут якось все більш по-дорослому, гнучкіше і крутіше + код чистий і красивий.
 
 

Посилання

 getmoai.com / — офіційний сайт
 getmoai.com / docs / annotated.html — доки
 moaiwebsite.github.io / — неофіційний сайт, пиляється співтовариством. Коли-небудь стане новим обличчям
 github.com / makotok / Hanappe — високорівнева Lua-фреймворк в ООП-стилі. З усіх подібних рішень тільки цей зараз розвивається і підтримується.
 
 Update:
 moaifiddle.com/Q09BJWGMW6/3 — js версія движка. Тепер можна погратися з движком без установки!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.