Доброго времени суток.
Начнем с того, что я не нашел на хабре туториалов по Cocos2d и Lua, поэтому мне пришлось много страдать и чтобы вы не повторяли моих ошибок я решил написать пост. В этой статье я расскажу как создать простую игру используя Сocos2d-x, Cocos Code IDE и Lua. Ранее, я уже писал про создание игр на Love2d. В этой статье я адаптирую старый туториал для кокоса и как это запустить на андроиде (Ни яблока, ни мака у меня нету).
Что нам понадобится?
Список важных вещей:
- Java JDK
- Сам Cocos2d-x. На момент выхода этой статьи вышел Cocos2d-x 3.2 и скачать его можно здесь. Нужно скачать той же разрядности, что и JDK
- IDE для lua. Разработчики движка постарались и выпустили свой IDE на основе Eclipse. Качаем здесь.
- [Windows-only]Python 2.7. Лежит вот тут.
Если вы хотите писать игры под андроид, то придется скачать еще пару вещей, а именно:
- Android SDK. Если вы не собираетесь писать под андроид, то лучше найти вкладку «GET THE SDK FOR AN EXISTING IDE»
- Android NDK. Я использую Android NDK r9, а с r10 возможны проблемы
- Apache Ant. У меня стоит 1.9.4
Установка
Сначала поставим Java JDK и Python. После распакуйте cocos2d-x и Cocos Code IDE (Если вы скачивали zip версию, если нет, просто запустите установку) в удобное для вас место. Распаковываем Android SDK, NDK и Apache Ant так же в удобное место. Путь к ним не должен содержать пробелов во избежание проблем. Открываем папку с SDK, находим SDK Manager. Запускаем и ставим нужные для нас версии API и всю папку Tools.
Запускаем Cocos Code IDE. В Window->Preferences->Cocos указываем нудные пути. У меня это выглядит так:
.
Теперь кликаем по вкладке Lua которая находится во вкладке Cocos и выбираем путь к cocos2d-x:
Настроено.
Немного теории
Cocos2d-x — кроссплатформенный движок, написанный на С++, был создан как копия Cocos2d. Cocos2d использует Object C и может использоваться только для iOS.
Теперь поговорим о базовой механике движка и сравним ее с Love2D. У кокоса все объекты находятся в слоях, а слои находятся в сценах. В Love2D ни слоев, ни сцен нету. Плюсы сцен и слоев в том, что с их помощью можно создавать гибкое приложение более простыми способами. Минусы в том, что для просто игры это может быть слишком громоздко и неудобно. В кокосе все представленно объектами и чтобы что-то появилось на экране надо просто добавить это на сцену, а в love2d все представленно простыми переменными и чтобы что-то появилось на экране нужно это каждый кадр рисовать. Это можно описывать достаточно долго поэтому я скажу вывод сейчас, а разницу вы сможете почувствовать сами. Cocos2d-x — большой движок с большим количеством возможностей, однако доступ к ним часто сделан не так как хотелось бы. Love2d — простой, не требующий много знаний, движок с отзывчивым коммьюнити, но с отсутствием многих нужных вещей, которые впоследствии пишут сами пользователи, но делают это вполне удачно.
А теперь сам код
Создадим новый проект. И у нас будет два файла в исходниках: hello2.lua и main.lua. Если вы не хотите посмотреть на чудо китайского гейм дева, то первый можно сразу удалять, а второй очистить. Он создан лоя демонстрации возможностей require. Открываем main.lua и видим кучу кода которая нужна чтобы понять как использовать порт под lua. Чтобы увидеть, что это такое нажимаем F11. Можно поиграться. Вот это бегающие существо это собака, а не белка как вы могли подумать. Посмотрели, поигрались и хватит. Удалите hello2.lua и весь код в main.lua и очизаем папку res. В папку res добавляем картинку и называем ее habr.png. Теперь пишем в main следующий код:
--Все классы кокоса require "Cocos2d" --Все константы кокоса require "Cocos2dConstants" -- Функция вывода сообщений cclog = function(...) print(string.format(...)) end -- Эта функция выводит ошибки function __G__TRACKBACK__(msg) cclog("\n----------------------------------------") cclog("LUA ERROR: " .. tostring(msg)) cclog(debug.traceback()) cclog("----------------------------------------") return msg end collectgarbage("collect") -- Предотвращает утечку памяти collectgarbage("setpause", 100) collectgarbage("setstepmul", 5000) --Теперь можно использовать файлы которые лежат в папках "src" и "res" cc.FileUtils:getInstance():addSearchResolutionsOrder("src"); cc.FileUtils:getInstance():addSearchResolutionsOrder("res"); --Записываем в константы гирину и высоту экрана SCREEN_WIDTH = cc.Director:getInstance():getWinSize().width SCREEN_HEIGHT = cc.Director:getInstance():getWinSize().height local function main() print("Resolution: " .. SCREEN_WIDTH .. "x" .. SCREEN_HEIGHT) --Запускаем главную сцену require "mainScene.lua" end --Вызываем функцию main local status, msg = xpcall(main, __G__TRACKBACK__) if not status then error(msg) end
В функции main мы вызываем файл mainScene.lua. В нем находится главная сцена игры. Создадим его и напишем туда следующий код:
-- Константы local NONE = 0 local ROTATION = 1 local SCALLING = 2 local MOVING = 3 -- Переменные local state, rotation, scale, ox, oy, delta, habrImage, moving -- Эта функция будет вызываться когда палец касается экрана local function onTouchBegan(touch, event) -- Включаем следующие состояние state = (state + 1) % 4 -- И возвращаем переменные к дефолту resetVariables() end -- Эта функция вызывается постоянно, а в dt хранится время с -- прошлого вызова. Если dt == 1.0, то с прошлого вызова прошла -- одна секунда local function update(dt) if state == ROTATION then --крутим картинку rotation = rotation + delta * dt elseif state == SCALLING then --увеличиваем scale = scale + dt * delta elseif state == MOVING then --Здесь немного посложнее, но все же просто: --Каждый раз мы увеличивыем переменную moving, а --потом берем ее за угол для косинису и синуса --и крутим картинку по кругу moving = moving + delta * dt local radius = 50 ox = radius * math.sin(moving) oy = radius * math.cos(moving) end -- В love2d мы использовали эти параметры при рисовании -- Здесь у нас спрайт и нам нужно постоянно менять ему -- все вручную -- Меняем размер habrImage:setScale(scale) -- Меняем угол habrImage:setRotation(rotation) -- Меняем позицию habrImage:setPosition(cc.p(SCREEN_WIDTH / 2 + ox, SCREEN_HEIGHT / 2 + oy)) end local function init() print("Creating main scene") -- Создаем сцену local mainScene = cc.Scene:create() -- Создаем слой с фоновым цветом -- Здесь я бы хотел поставить паузу и рассказать более подробно -- потому что у меня ушло 2 часа чтобы узнать как мне изменить цвет -- фона. 1) В C++ нету функции cc.c4b(r,g,b,a) поэтому мне пришлось -- догадаться, что нужно смотреть не на C++ таких случаях, а на -- cocos2d-x-js, т.к. он более популярен чем cocos2d-x-lua -- и если вы не можете найти нужную функцию в C++, то ищите ее в -- JavaScript версии, однако это не поможет с евентами local gameLayer = cc.LayerColor:create(cc.c4b(255, 255, 255, 255)) -- Создаем спрайт habrImage = cc.Sprite:create("res/habr.png") --Ставим его смещение по центру habrImage:setAnchorPoint(0.5, 0.5) --Ставим позицию на центр экрана habrImage:setPosition(cc.p(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)) --Добавляем его к слою gameLayer:addChild(habrImage) state = 0 resetVariables() -- Чтобы функция update вызывалась нужно сообщить кокосу, что ее нужно -- вызывать cc.Director:getInstance():getScheduler():scheduleScriptFunc(update, 0, false) -- Создаем лисениры для событий. Хочу обратить внимание, что для каждого -- типа событий есть свой лисенер. local listener = cc.EventListenerTouchOneByOne:create() -- Говорим лисениру, что такой то тип событий связвн с такой то функцией listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN ) -- Добавляем лисенер к слою local eventDispatcher = gameLayer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, gameLayer) --Добавляем слой к сцене mainScene:addChild(gameLayer) --Запускаем или если уже что-либо запущено заменяем сцену if cc.Director:getInstance():getRunningScene() then cc.Director:getInstance():replaceScene(mainScene) else cc.Director:getInstance():runWithScene(mainScene) end end function resetVariables() rotation = 0 scale = 1 ox = 0 oy = 0 delta = 20 moving = 0 end --Запускаем сцену init()
Теперь немного о помощи с поиском ответов. Во-первых: Порт на луа практически идентичен С++ и основные отличия можно прочесть здесь. Во-вторых: как я ранее писал, если вы не можете найти что-либо в порте С++, то попробуйте поискать эту проблему для JS движка. Он более популярен чем луа, однако в нем есть множество отличий, но очень часто он мне помогал. Чтобы запустить то, что у нас вышло нажмите F11. Чтобы запустить на андроид нажмите на кнопку «Debug configurations» и выберите андроид. Для запуска нужен настроенный adb, но про это и так много статей, поэтому я не буду писать здесь об этом. На этом все Спасибо за прочтение (:
Вот что вышло в итоге:
ссылка на оригинал статьи http://habrahabr.ru/post/232013/
Добавить комментарий