Citadel Of Hope

Спустя три месяца наконец-то зарелизили превью версию нашей TD’шки.

Level 3

Это самый большой проект, среди игр, в котором я принимал участие. По личным ощущениям, игра готова процентов на 80, осталось только доделать уровни, прикрутить межуровневые апы, ачивки, и сюжет. Так что, возможно в следующем месяце, уже будет счастье и релиз.

Технические няшки:

Игра вся растровая + видео (flv) анимации. Т.е. тут и предварительный рендер в битмапы всех FLV’шек, и динамический фпс у всего и вся, для поддержки игрового ускорения.
Все настройки баланса, волн, башен, и прочее, подгружаются из дропбокса геймдизайнера. Мегаудобно!
Внутри встроена система статистики, которая иногда делает скриншоты уровней, собирает различную информацию, и часть из нее уже шлет к нам на рассмотрение, а другую часть возможно будет слать, как только поймем какая информация нам нужна.
Поддержка сценариев, для сюжета. Правда сделано это достаточно криво, на внутриигровых событиях, и нормальную архитектуру для реализации такой штуки, я в голове еще собрать не могу. Пытался воткнуться в рантаймовые компиляторы для as3, чтобы вынести разработку сценариев либо в редактор уровней, либо к гд, но как-то пока не сложилось.

Асинхронный A*

Обычно для задачи поиска пути, я использовал найденный давным давно в интернете класс – http://snipplr.com/view/29715/astarmap-pathfinding-grid-use-with-astar-class/. С задачей он справлялся отлично, но имел один сильный минус, а именно – при поиске длинного пути на достаточно большой карте, он отъедал от кадра кучу времени. Если же этих поисков было несколько, то несмотря на высокий средний фпс, дергания убивали все затеи.

Посидев, и разобравшись с алгоритмом, хочу представить свою версию реализации A* с возможностью асинхронной работы. Т.е. вы можете оставить заявку на поиск, и через несколько кадров/секунд, когда поиск будет закончен, вам в коллбэк прилетит результат. В качестве бонуса, данная реализация вышла быстрее представленного класса по ссылке в 2-7 раз, в зависимости от условий. Алгоритмических оптимизаций никаких не применялось, и если необходимо, их можно будет легко навернуть на то что есть, и заменить эвристическую функцию, сейчас это:

H = (|mtx - x| + |mty - y|) * 10;

Двумерный массив представлен в виде одномерного вектора, с доступом по координатам – map[x*mHeight + y], и реализован в классе Map2D. Класс PFSession – содержит необходимые данные для осуществления поисковой сессии, размазанной по времени. И класс PFMap – для работы со всем этим.

Пример использования:

// Создаем карту заполненную пустыми клетками
var map:PFMap = new PFMap(100, 100);
// Значения для клеток меньшие 0 являются непроходимыми,
//0 - идеально проходимая точка
//Все что выше нуля - вес клетки, который учитывается при построении пути (желательно делать кратным 10)
map.setCell(10, 10, -1);
map.setCell(10, 11, 10);

// Ищем путь от точки 0,0 до точки 99,99
// Возвращенный вектор содержит массивы с координатами вида [x,y], от начальной, до конечной точек
var path:Vector<Array> = map.findPath(0, 0, 99, 99);

// Асинхронное использование
stage.addEventListener(Event.ENTER_FRAME, function (e:Event):void {
    // Чтобы асинхронно использовать поиск, нам нужно каждый кадр просчитывать необходимое
    // количество итераций, оптимальное количество зависит от размеров карты и количества юнитов
    // Здесь мы каждый кадр просчитываем 50 итераций
    map.update(50);
});

// Асинхронные вызовы
map.findPathCallback(0, 0, 50, 50, function (path:Vector<Array>):void {
    trace("Path founded!");
});

map.findPathCallback(0, 0, 40, 40, function (path:Vector<Array>):void {
    trace("Path founded!");
});

В качестве первого места куда нужно заглянуть, это планировщик в PFMap.update, сейчас он до ужаса примитивный, но для большинства вещей его хватит за глаза.
При задании весов клеткам, необходимо учитывать, что G в данной реализации равно 10 (или 14, если движение по диагонали) + Вес.

Флешки: (колесико для зума, левая кнопка для перетаскивания)
Синхронный режим: 100х150, 100 юнитов – http://megaswf.com/serve/1098310
Асинхронный режим, те же параметры: http://megaswf.com/serve/1098309

Как видно – минус асинхронного режима, что при сохранении фпс, много юнитов очень долго ждут пока их путь будет найден. Эта проблема решается нахождением золотой середины для аргумента update, и применением дополнительного поведения. Например – юнит запросил планирование пути, а в этот момент идет к цели по прямой, либо с простым алгоритмом обхода, как только путь будет найден, корректирует свой на более правильный.

Возможность хождения по диагонали включается в конструкторе PFSession.
Вот код: http://blog.poppergames.com/wp-content/uploads/2011/04/pathfinding.zip

Ошибки, улучшения, слова “так пишут только му**ки”, можно писать на мыло, или в комменты.

Всякое и андроид

Последние месяцы был адский завал, и писать особо времени не было.
Случилось поработать со Spil Games, что тянется по данный момент. Начиналось все с того, что они купили праймари лицензию на Arrows Ruler в декабре. Контракт заключили с условием, что я вышлю все до 30 января, переводы текстов обещали в течение 4 недель и приложили к письму многомегабайт документации.
Брендинг у них – тоска голимая. Требуется локализация игры на н языков, и ~3 разных версии для их порталов. Отличаются они не сильно, но у меня компоненты из их api не заработали без напильника.
Переводы прислали ~4 февраля.
Тестируют присланные им версии от 1 до 2 недель.

Но несмотря на это, есть плюсы. Мартина отвечает очень оперативно, когда дело дошло до конца февраля, в предверии конференции, они выслали мне деньги, не закончив процесс брендинга. Я так понимаю, можно было еще вначале февраля их об этом попросить, но если буду работать с ними еще, надо настаивать на оплате сразу после заключения контракта. Иначе состариться можно.

Еще одно важное событие – случился релиз на андроиде.
Сделали мы ее совместно с Wheemplay ltd в лице Стефана Кейша. Они же выступают издателем. Сотрудничество мегаприятное и удобное, чего только стоит новый арт.
С нетерпением жду результатов через месяц, чтобы понять – чего ожидать от андроида.

Анимированные переходы между кадрами

Сделал в одной игре “модные” переходы между менюшками, с блюрами, блэкджеком и девицами.
Вот простой пример, и код как это сделать.


Теория очень простая. Рисуем в битмапу кадр, ждем, пока переключимся на следующий, рисуем второй, двигаем их вместе, в конце движения – удаляем битмапы.
Если на сцене что-то меняется во время перехода, лучше добавить слушатель и обновлять битмапу.

Код основного класса котят сверху:
(more…)

Android

Внезапно:

А началось все с того, что Arrows Ruler нашла праймари спонсора, почти сразу после того как была закончена. Сумма для 15 часов, более чем адекватная, и я решил немного “отдохнуть” и заодно потыкать андроид.
Андроид как платформа оказался достаточно приятным и “потыкать” выросло в полноценный порт движка, а потом игры (нет только хайскора, разве что).

Суммарно – дофига часов, сюда входит начальное не понимание основ, и слабое знание Java, однако со временем во все въехал и сейчас все кажется достаточно прозрачным. Монетизацию выбрал через рекламу, паблишера искать не буду. Если окупятся 25$ для регистрации в маркете, буду рад. Как залог на будущее – назвал игру с постфиксом Lite, вдруг чего, так запилю платную версию без рекламы и доделаю хайскор.
Паблишить думаю после нового года, как раз закажу няшные иконки и промо, ну и может чего придумаю еще. О результатах отпишусь.

Arrows Ruler

Начитался литературы по гейм-дизайну и решил попробовать сотворить чего-нибудь казуальное. В мелких масштабах, без привлечения художника.

Идея

Идея родилась спустя пару часов – матч3 с не совсем обычной механикой. А именно – есть стрелочки, которые двигают ряды в соответствующем направлении. Т.к. элементов нужно было больше, чтобы игра не превратилась в “кликни и смотри как все взрывается”, добавил еще один – он “поворачивал” элементы вокруг себя. Работало это иногда совершенно непонятно (например если рядом с одной стороны нет элементов), и после первых тестов, оказалось, что нужно бы добавить еще один элемент. В итоге этот “поворачивающий” я выкинул, а добавил два, которые меняют соседние элементы местами – вертикально и горизонтально.

Код

Признаться, я никогда не делал матч3, но всегда думал, что у них у всех одинаковый движок, и делать их – проще некуда. Однако либо я дурак, либо архитектура которую представляет мой движок, но переписывал я все три раза, пока не нашел красивого решения. Т.к. выделенное время подходило к концу, в качестве анимации везде использовал TweenMax, какие-то куски кода брал из старых проектов, в общем слепил из того что было на скорую руку.

Графика

Это была самая большая проблема в этой игре. Т.к. делать все я решил сам, а в школе на уроках изобразительного искусства я еле вытягивал тройку.
Немного подумав решил, вот найду похожую игру, без зазрения совести украду цветовую схему, и перерисую все примитивами. Собственно так и вышло. Жертва – откуда я украл цвета (надеюсь авторы не будут в обиде) – Deep Trip.
В итоге вышло достаточно няшно, а с анимациями и эффектами, и того лучше.

Генератор частиц

Эксперимента ради, посмотрел на stardust particle engine. Штука – крутая, прикрутил его в качестве генератора белых пузыриков при взрыве.

Дальше все просто, библиотека роялти фри звуков от Sony, 7 баксов за мелодию в melodyloops, иконка, первый фидбек, поправил немного графику, записал трейлер.

Итого: 14-15 часов работы, красные глаза и недосып.
Завтра закончатся выходные и буду рассылать спонсорам. Если спонсор найден не будет (а вероятность достаточно высока), спонсором стану сам и почувствую на себе этот первый опыт, да и портал зашевелится.

Трейлер:

Ссылка на игру: http://www.flashgamelicense.com/view_game.php?from=dev&game_id=15330

О пользе First Impressions

Знаете, есть такая штука на FGL – First Impressions. Ее дарят по пять штук за каждый полученный маркет левел, или можно купить несколько штук за несколько долларов. В идеале она выглядит так – Анонимный пользователь (ревьюер), видит вашу игру на специальной странице сайта, играет в нее минимум пять минут, а потом оценивает по параметрам Easy Of Use, Fun, Graphic, Sound, Polish и пишет комментарии.
Пользовался я этой услугой несколько раз для нескольких игр (дарят ведь, не просто так лежать).
За эти несколько раз я выявил зависимость, ревьюеры делятся на несколько типов:

1) Ставят наивысший балл, и описывают, какая ваша игра замечательная (для самолюбия полезно, для игры – нет)
2) Ставят средний балл, и пишут достаточно субъективные вещи
3) Ставят низкий балл, и не объясняют почему
4) Ставят разный балл, в зависимости от игры, и пишут действительно логичные вещи, которые хочется и нужно исправить (1 из 20ти оказывается таким).

Стоит ли покупать эти FI? Мой ответ – нет, они бесполезны в большинстве случаев.

Спиды

Результаты моего тестового спид-проекта, о котором я писал чуть менее чем два месяца назад, почти подошли к концу. Остался только брэндинг.
Редакторский рейтинг на фгл – 8.5, попала в Hidden Gems + Games Spotlight (хотя, скорее всего из-за способствованию продажи одним человеком).

Как итоги – это самая успешная моя на данный момент игра в пересчете на дни/профит. Ну и она фанская.
Риски в таких быстрых проектах – минимальны (потерять три дня != потерять три недели), энтузиазм не успевает утихнуть, а организм не успевает устать. Однозначно буду экспериментировать дальше.

Книга “Programming Game AI by Example”

Разрабатывая AI для одной стратегической игры, ушел в интернеты для обзора вопроса. К слову, до этого момента дальше конечных автоматов, ничего использовать не приходилось, а тут они не подходили никак.
В поисках, наткнулся на одну шедевральную книгу от Мэта Баклэнда (Mat Buckland) – “Programming Game AI by Example”. Книга начинается с мат. аппарата (тригонометрия, физика), потом описываются конечные автоматы, теория графов, скрипты в играх. Все это изложено понятным языком, с картинками и отличными примерами. Дальше автор рассказывает о создании top-down шутера (quake like) и применяет паттерн Goal-Driven Agent Behavior, подробно рассказывает про Path Planning и переходит к теории нечетких множеств, нечеткой логике и применении всего этого в геймдеве.
К сожалению (?), книга доступна только на английском.

Книга есть сами знаете где, а также можно купить ее, например, на озоне за цену (конскую) в 4 тысячи рублей (http://www.ozon.ru/context/detail/id/1833221/).
Считаю, что если вы делаете игры, и новичек в вопросе ИИ – ознакомиться нужно обязательно.

Организация “скелета” игры

Этот пост вряд-ли пригодиться кому-либо, кто уже имеет опыт создания флэш игр, но может быть полезен начинающим. В нем я хочу продемонстрировать простейший “скелет” для игры (прелоадер, сплэш скрин, игровое меню, разные другие меню, запуск игры).

Теория

Теорию внутреннего прелоадера я вычитал здесь. Если по-простому – все ресурсы прелоадера экспортируются в первом кадре, все остальное – в третьем. Сама флэшка имеет Document Class – прелоадер, и три кадра. В первом – работает сам прелоадер, в третьем – находится “игра и все что с ней связано”.
Прелоадер контролирует процесс загрузки, и рисует красивый прогресс-бар, пишет разные цифры, и т.п. Когда загрузка флэшки завершена, переходит на третий кадр, и отдает управление игровому контроллеру, который находится внутри третьего кадра.

Игровой контроллер представляет из себя символ с кадрами “состояний”. Т.е. первым делом имеет кадр “splash” – в котором показывается n секунд сплэша спонсора. Имеет кадр “menu” – для меню игры. Кадр “game” – в котором создается и рисуется игра классом игры. Также кадры “shop” – магазин, “select_level” – меню выбора уровней, “submit_highscore” – отправка хайскора, и так далее.
Игровой контроллер имеет методы для перехода в каждое из этих состояний. Т.е. мы создаем кнопку “Старт”, она вызывает метод startGame игрового контроллера, он переключается на кадр “game” и создает там игру. Когда в игре нажимается кнопка “shop” – игровой контроллер уничтожает инстанс игры (если нужно), и переключается на кадр “shop”, где у нас отрисован магазин.
Все это достаточно просто, ниже есть описание того, как сделать эту базу, и исходный код.

(more…)