[Из песочницы] История о создании игры
Статья будет о создании второй по счету моей игры под Android, на кроссплатформенном движке Cocos2D-x (v3.1). Код преимущественно на С++, местами Java и Lua. Попытаюсь вкратце рассказать про основные моменты разработки.
ВступлениеПрошел ровно год как я серьезно решил попасть в индустрию. Тогда разработка под мобильные платформы казалось невероятно перспективным, а разработка таких, относительно простых, игр — простой. Будучи 18-летним студентом с небольшим навыком программирования и работы с графикой, но с огромными амбициями хотелось делать что-то свое, что-то огромное и совершенное. Реальность быстро поставила на место и было решено сделать что-то маленькое, но максимально использовать весь свой опыт и навыки. Отсутствие ограничений во времени и отсутствие ответственности перед собой растянуло разработку игры и выход в Google Play состоялся аж в конце марта текущего (2014) года. Несмотря на весьма теплые отзывы на разных форумах, результаты совсем не порадовали — 200 загрузок за все время и около 0.30€ с рекламы.Первый блин — комом Разочарование только добавило азарта. Проанализировав неудачу и прочитав немного литературы, через полтора месяца решил написать что-то простое чтобы вложиться в месяц-два разработки. Сказано — сделано! Я захотел сделать головоломку-пазл. Суть игры в том что дается изображение и элементы изображения в разных формах (полупрозрачные и перевернутые, например) и нехитрыми манипуляциями надо поставить их на место.
Первый уровень Cocos2D-x Cocos2D-x — порт популярного движка под iOS. Бесплатный и кроссплатформенный. Если вы только решаете начинать делать игры под мобильные устройства и не знаете какой движок выбрать, обязательно рассмотрите его как вариант.Преимущества, которые стали ключевыми:
кроссплатформенность C++ разработка в Windows, с последующим переносом на Android поддержка Lua открытый исходный код Отсутствие полноценной документации и уроков усложняют начало работы с движком, но в целом он себя проявил очень хорошо. К тому же комьюнити постоянно расширяет функционал и документацию. Позволяет писать 2D игры практически любой сложности, так как можно вызывать функции OpenGL ES напрямую.
Если кому-то будет интересно то могу написать небольшой туториал по созданию «Hello, world!» и основным моментам.
Концепт Итак, как было сказано выше, концепт игры в том что дается картинка и некоторые ее части (элементы) разбросаны в разных местах. Задачей игрока является поставить все элементы на свое место. Элементы могут иметь разные свойства, например: вращение, прозрачность, изменение размера и т.д. Также должна быть возможность создания разных форм и разного поведения.Пример уровня с вращающимися элементами Дизайн Возможности нанять профессионального дизайнера нету. Было решено сделать максимально простой дизайн, без лишних деталей и мне кажется что я в достаточной мере справился с этой задачей.Меню выбора уровня Завершение уровня Слева — выход в меню выбора уровня, центр — название изображения и автор, справа — переход на следующий уровень.
В качестве иконок для Google Play и самого приложения использовал скриншот одного из уровней.
Все виды иконок
Реализация уровней
Из описания ясно что главной задачей есть создание такого кода, который без проблем бы позволил создавать разные уровни без перекомпиляции, и при этом сохранять достаточную гибкость для создания элементов разных видов. Для этих целей были выбраны XML и Lua. XML описывает уровень, позиции элементов, их позиции на картинки, форму, прозрачность, размеры и т.д. А также имеет теги, в которые можно вставить кусочки кода написанного на Lua.Пример описания одного из уровней на XML
if 150 > e4Opacity then
e4Opacity = e4Opacity + 1
element: setOpacity (e4Opacity)
end
if 150 > e2Opacity then
e2Opacity = e2Opacity + 1
element: setOpacity (e2Opacity)
end
if 200 > e1Opacity then
e1Opacity = e1Opacity + 2
element: setOpacity (e1Opacity)
end
С помощью Lua можно писать такие функции как:
onCreate — вызывается при создании элемента onTouchBeganFunction — вызывается при «прикосновении» к элементу onTouchMovedFunction — вызывается при перемещении прикосновения onTouchEndedFunction — вызывается при окончании прикосновения onUpdateFunction — вызывается при обновлении элемента onDestroy — вызывается при уничтожении элемента В каждую функции передаются такие переменные как сам эелемент, спрайт элемента, спрайт формы, уровень и спрайт уровня. В функции «onTouch» также передается переменная типа «Touch», которая имеет в себе такие данные как положение прикосновения или предыдущее положение. В связи с тем что Cocos2D-x поддерживает Lua, то можно работать с функциями и объектами Cocos2D-x напрямую, передавая их в качестве аргументов. Такая реализация уровней получилась достаточно эффективной и очень гибкой (ведь даже можно, например, закрыть игру при нажатии на элемент или управлять другими элементами).
Реализация вызова Lua-функций элементов на Cocos2D-x выглядит так (на примере функции onCreate, которая вызывается при создании элемента):
Скрытый текст if (! m_scriptFunctionOnCreate.empty ()) { LuaEngine* engine = LuaEngine: getInstance (); LuaStack* luaS = engine→getLuaStack (); luaS→executeString (m_scriptFunctionOnCreate.c_str ()); lua_getglobal (luaS→getLuaState (), «onCreate»); luaS→pushObject (this, «cc.Node»); // element luaS→pushObject (m_sprite, «cc.Sprite»); // element sprite if (m_shapeMaskSprite!= nullptr) { luaS→pushObject (m_shapeMaskSprite, «cc.Sprite»); // shape } else { luaS→pushNil (); } luaS→pushObject (getParent (), «cc.Node»); // level luaS→pushObject (((Level*)getParent ())→getLevelSprite (), «cc.Sprite»); // levelSprite lua_call (luaS→getLuaState (), 5, 0); luaS→clean (); } Вместо заключения Основной целью создания этой игры было скорее «сделать, чтобы сделать», поэтому нету никакого ожидания успеха. Возможно в ближайшем будущем выложу её исходный код в свободный доступ.Если будет интересно, то в следующих статьях расскажу про подключения AdMob и Google Analytics в игру, написанную на Cocos2D-x.