Mining Truck. Немного о создании уровней

До того, как я начал работу над игрой, я думал, что новый и интересный опыт меня ждет в работе с физической библиотекой Box2D, но к моему удивлению все оказалось не так.

С физической библиотекой Box2D я разобрался относительно быстро и без серьезных проблем. А самая интересная задача как раз встала в тот момент, когда дело дошло до создания уровней. Я уже немного затрагивал эту тему в одной из прошлых своих записей. Так вот, передо мной встала задача: как просто, быстро и наиболее оптимально создавать игровые уровни в играх типа Elasto Mania!?

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

Пример с тайлами

На данной картинке видно мою попытку создать уровень из отдельных блоков с уникальными формами.

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

Недостатки данного подхода:

  • некрасивые тайловые стыки;
  • ограничения на создание игровой поверхности;
  • необходимость в сложном редакторе уровней.

 

Пересмотрев пару десятков игр этого же жанра я увидел, что каждый игровой уровень в таких играх — это практически отдельная большая картинка, нарисованная специально для каждого уровня, а уже где-то в коде игры создается для нее физическая маска. Такой подход мне пришелся по душе, поскольку он упрощает разработку редактора уровней или вовсе позволяет от него отказаться. Но он так же имеет свои недостатки.

Недостатки данного подхода:

  • проблемы с производительностью при обработке больших изображений;
  • большой размер игры, если уровень хранится в виде растрового изображения.

 

Таким образом, самым лучшим решением в моем случае будет использование обоих вариантов. То есть, весь уровень создается прямо во Flash IDE, рисуясь и составляясь из отдельных клипов — это решает проблему большого размера игры. Так же физический образ уровня создается во Flash IDE, чтобы не писать для этих целей редактор.

Я записал небольшой видео ролик, чтобы не писать много текста о процессе создания уровней.

Видео ролик, демонстрирующий процесс создания одного из уровней. Видео ускорено на 2000% Музыка: All The People Now — Clann Zu. В общей сложности на разработку каждого уровня уходило по 2-3 часа.

Как видно из ролика, поверхность уровня и некоторые другие детали рисуются прямо в клипе с уровнем. После чего физическая форма уровня задается специальными клипами-пустышками, они нужны лишь для того, чтобы потом на основе их положения и поворота создать физические тела в движке. Только после того, как форма уровня отлажена — начинается уже процесс оформления уровня. В качестве оформления используются заранее заготовленные повторяющиеся клипы из библиотеки, которые расставляются как угодно и где угодно. А сам уровень делится на три слоя: задник, основной слой с игровыми объектами и передний слой. Таким образом, получаются довольно разнообразные уровни, использующие повторяющуюся графику.

Оптимизация игровых уровней

Основной задачей для меня стало решение проблемы производительности в игре. Оказалось что во Flash IDE область для рисования совсем не резиновая. Ограничение на рабочий холст во все стороны от центра рабочей области не может быть более 10 000 px, то есть, нельзя создать холст более чем 20 000x20 000 px Я же в ходе небольших экспериментов вычислил, что длина игрового уровня в 10 000 px будет самым оптимальным в плане продолжительности уровня и его оптимизации. Но даже при 10 тысячах были глюки и тормоза именно при работе с самой средой Flash. Чтобы всего этого избежать, я разбил каждый уровень на три части по 3200 px в ширину и 640 px в высоту — так мне удалось избежать проблем самого флеша при создании уровня.

Конечно, двигать три клипа 3200x640 с вложенным в них множеством других клипов в векторном формате — это просто тихий ужас для производительности. Поэтому тут безусловно их нужно растезировать в момент загрузки. Но и растр в таком размере тоже не будет быстрым. В итоге, каждую часть уровня в момент растеризации пришлось делить еще на несколько равных частей. То есть, в результате, каждая из 3х частей уровня разрезается на 10 кусков размерами 320x640 px, и все эти куски сохраняются в виде битмапов в массив. ? так каждый уровень после загрузки состоит в памяти из 30 кусков - словно небольшие паззлы большой картинки :)

Далее все эти куски сразу получают положенные им места в игровом мире, но не добавляются в игровой мир до тех пор, пока они не попадут в область видимости. Это означает, что одновременно на экране не может присутствовать более 3х кусков игрового уровня.

Все эти не хитрые манипуляции непременно дали хорошую производительность, но проверить это на примере у меня не получилось :) То есть, заведомо непроизводительное решение я делать не стал. А при тестировании реализованного варианта на всех доступных мне компьютерах я получал максимальное кол-во fps. Самый слабый из компьютеров в моем распоряжении только MacBook Air 1,6gHz, 2gb RAM.

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

Когда начались жалобы со стороны пользователей на производительность игры, я, конечно, расстроился и начал было смотреть свой код на возможные слабости. Но вот не задача, претензии были, а конфигураций компьютеров не было. ? только в одном случае удалось выяснить конфигурацию, а в остальном претензии на производительность игры без оглашения конфигурации — я считаю не обоснованными. Мало ли на каком нетбуке пользователь пытается запустить достаточно требовательную Flash игру и при этом жалуется на то, что она у него тормозит :)

Хранение уровней

В одном из прошлых постов в комментариях немного затрагивался вопрос сохранения уровней, и там писали о том, что по хорошему не нужно парсить сам клип на предмет его содержимого для создания уровня в игровом движке — с этим согласен. Оптимально экспортировать нарисованный клип в xml или ему подобный формат в виде параметров объектов и потом на основе этих данных уже строить уровень в игровом движке. Но я лично так делать не стал, и в игре «Mining Truck» загружается именно клип с уровнем, на основе которого создаются все физические объекты для игры. Обоснование такому подходу достаточно простое, клип с векторной графикой в любом случае приходится загружать для того, чтобы создать его растровую копию. Так зачем же тратить время на экспорт данных в xml и в будущем писать код для разбора этого xml, когда данные о физических объектах очень просто можно получить одновременно с созданием растрового образа уровня!? :)

То есть, из клипа с уровнем, в котором размещаются объекты из обычной флешовой библиотеки, при его разборе создаются реальные игровые объекты, используя координаты и развороты пустышек, размещенных в клипе с уровнем. После того как все физические объекты созданы и все пустышки обработаны — они скрываются из клипа и создается растровая копия графики уровня, а далее векторный клип-оригинал вовсе удаляется из памяти и в игре больше не участвует.

Это пожалуй основные сложные моменты на обдумывание и шлифовку которых я потратил больше всего времени.

 

Если честно никогда не думал что на оптимизацию уходит столько времени. =) Зато у всех друзей которых я заставил поиграть с производительностью всё было отлично, хотя у некоторых компьютеры не первой свежести. :) Поздравляю тебя с большой и успешно проделанной работой. ;)

Кирилл
2 Марта 2010
— 07:41
#

Отличый ролик! На то как уровни рисуются и оптимизируются сами собой можно смореть часами )). Молодец, Антон, радуешь регулярными постами!

flazm
2 Марта 2010
— 08:59
#

Твои ролики смотреть одно удовольствие. Вдохновение!!! Ещё как дизайнер, узнаю новые фишки ctrl+C/ctrl+V ))) как ты интересно всё расставляешь)

J0x
2 Марта 2010
— 11:24
#

Ролик супер! Вдохновляет своей красотой!
З,Ы А когда примеро будет закончена игра про Грибника, а то жуть как поиграть охото!!!

Руслан
2 Марта 2010
— 13:22
#

Спасибо! Отличная игра! Вы отлично потрудились! Всегда приятно смотреть на работу профессионала... Очень круто..
А как вы скроллинг реализовали? расскажите пожалуйста. Всегда было интересно как можно такое сделать с Box2d. Мне вообще казалось что этот движок только для одного экрана, ну может 100-200 пикселей вокруг.. но 10000 это круто =)

Alexander
2 Марта 2010
— 17:08
#

Супер!!! Очень интересно, бросило в раздумья :)

VirtualMaestro
2 Марта 2010
— 17:29
#

@Кирилл, на все, что делается в первый раз, уходит достаточно времени. Зато потом уже все в разы быстрее ;) Спасибо!

Ant.Karlov
2 Марта 2010
— 17:37
#

@flazm, спасибо! Рад, что не зря стараюсь :)

@J0x, а я то думал, что уж прием с copy/past всем известная фича :)

Ant.Karlov
2 Марта 2010
— 17:39
#

@Руслан, Грибник почти готов и я уверен, что он будет следующей игрой которую я закончу. А вот когда точно состоится релиз, мне пока сложно прогнозировать, все зависит от того как быстро найдется спонсор и утрясутся основные вопросы. Но на FGL игра точно появится в этом месяце.

Ant.Karlov
2 Марта 2010
— 17:42
#

@Alexander, большое спасибо за лестный отзыв! Про скроллинг на Box2D в двух словах не рассказать, но на деле как обычно все достаточно просто. Думаю в будущем открыть небольшой цикл постов о Box2D, но это только тогда, когда по лучше его узнаю.

Ant.Karlov
2 Марта 2010
— 17:47
#

@Ant.Karlov copy/past всем известен, но чтобы им пользоваться вот так грамотно, не все умеют))) где-то повернуть где-то затемнить, где-то чуток изменить и т.п.))

J0x
2 Марта 2010
— 20:55
#

Отличный пост . Больше всего поражает видео и процесс графического оформления уровня. Удивляет то как в тебе уживается программист с дизайнером :) Открой секрет ?

FlashRushGames
3 Марта 2010
— 01:23
#

Сталкивался с похожим вопросом оптимизации графики, когда ещё работал в рекламе. Во fla-файле всё было нарисовано рукой, без использования векторов. ?сходник весил более 60 mb при 512mb оперативной памяти на том железе:)
тоже разбивал на куски и переводил в растр.
Пост хорош.
ps А в каком редакторе код правишь?

Bakame!
3 Марта 2010
— 07:40
#

(Однако быстрый у тебя движок на сайте! Поражен.)

Bakame!
3 Марта 2010
— 07:41
#

@FlashRushGames, я даже и не знаю в чем секрет, как-то вот так получилось :)

Ant.Karlov
4 Марта 2010
— 00:34
#

@Bakame!, по идеи исходник всегда больше размером чем готовый .swf. Например, fla грузовиков 36 мб, а на выходе всего 2 мб. Вектор на самом деле оптимальнее в плане размеров чем растр, зато с производительностью у него хуже.

Код пишу в TextMate — отличный редактор, причем не только для AS3, но и для любых других языков. Только он исключительно под MacOS.

Ant.Karlov
4 Марта 2010
— 00:39
#

Да, возможно к лету буду пользоваться TextMate)
да, с выходом в swf — вектор дружит лучше:)
Спасибо за комментарий.

Bakame!
4 Марта 2010
— 10:19
#

Молодец!!!
Просто шикарно!

FreeS
4 Марта 2010
— 14:17
#

новый дизайн у блога - отличный.
как буд-то снова держу в руках game-exe :)

yailenko
7 Марта 2010
— 01:37
#

Хотел у вас спросить: с чего начать разработку флеш игры? Можно ли сделать ее только в программе Flash Mx(естественно с ActionScript).

PRIZRAK
23 Марта 2010
— 15:25
#

@PRIZRAK, лично я начинаю разработку игры с проработки идеи в голове, потом когда в голове идея более менее сформировалась рисую наброски на бумаге. Далее из оцифрованных набросков составляю графический прототип в Photoshop (об этом я писал уже в последних записях), ну а далее уже становится достаточно понятно, что и в какой последовательности делать.

Во Flash MX игру можно сделать, да.

Ant.Karlov
24 Марта 2010
— 14:35
#

Спасибо. Попробовал, но не понимаю как компилировать файл. Чтоб потом он мог например в браузере отображаться.

PRIZRAK
24 Марта 2010
— 19:27
#

Антон такой вопрос
вот у тебя уровень состоит из слоев получается 3 слоев.
Ты хранишь каждый слой уровня в отдельном мувике, и все 3 у тебя в уровне лежат?? или как
Ты отдельно для каждого слоя строишь битмап (для производительности)?
Спасибо.

Mset
25 Марта 2010
— 15:24
#

копи/пасте это хорошо, но ctrl+d наверно удобнее в данном случае

YETI_UA
29 Марта 2010
— 17:41
#

@PRIZRAK, чтобы флеш отображался в браузере его надо специальными тегами вставить в html страницу. Думаю, что на этот вопрос очень легко ответит гугл. Так же во Flash есть специальная команда которая сама создает html файл и вставляет в него html код чтобы ролик отображался на странице. Не помню где эта команда во Flash под Windows, но у меня она в меню File > Publish Preview > Default - (HTML)

Ant.Karlov
2 Апреля 2010
— 02:29
#

@Mset, когда создается уровень, каждый слой лежит в одном клипе на разных слоях внутри клипа — это чтобы было проще декорировать видя как все между собой стыкуется. Когда уровень нарисован я разделяю уровень на два клипа, в первом объекты для заднего слоя, во втором для переднего, а потом при загрузке уровня с этих клипов создаются уже битмапы.

В самой игре конечно три слоя, но в третьем слое находятся только игровые объекты и создаются они программно извлекая координаты объектов из основного слоя.

Ant.Karlov
2 Апреля 2010
— 02:36
#

@YETI_UA, самое удобное — это кликнуть в клип на сцене и с зажатым alt тянуть клип в новую позицию ;)

Ant.Karlov
2 Апреля 2010
— 02:38
#

Это одна из самых полных статей, которые мне попадались! Меня очень интересовал этот вопрос, и вот ответ! Спасибо большое!

Дмитрий
29 Апреля 2010
— 22:07
#

А как вы блоки пустышки (которые используются для проверки столкновений ) в коде привязали? каждый блок имеет своё уникальное имя?

?ван
6 Мая 2010
— 14:21
#

Привет, хочу немного уточнить.
У тебя каждый слой состоит из 30 кусков ?
т.е. задник - 30, основной - 30, и передний - 30 ?
? сколько это всё жрёт оперативы ?
Возможно жаловались люди у которых её мало ?

Frees
28 Мая 2010
— 17:41
#

@?ван, блоки пустышки не имеют имен. ?мена имеют только те спрайты которые являются разнотипными и динамическими, например бочки, ящики и другой дорожный мусор. Только имена у них не уникальные, а по типу объекта — "box", "barrel" и т.п. В первую очередь обрабатываются все клипы имеющие уникальные имена, а потом клипы безимянные. Вся остальная графика не имеющая отношения к физическому миру расставляется на сцене под типом Graphic и исключается из обработки в коде через if (level.getChildAt(item) is Sprite) { ... }

Ant.Karlov
3 Июня 2010
— 17:39
#

@Frees, да, получается, что каждый слой делится на 30 кусочков. В грузовиках я оперативку мерил на ранних этапах, а потом перестал, поэтому сколько точно жрет оперативной памяти сейчас уже не скажу. Если интересно, то на досуге могу профайлером посмотреть. Но жалоб от пользователей не было.

Ant.Karlov
3 Июня 2010
— 17:52
#

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

1. На видео рамки видно, я так понял что это и есть границы тех кусочков. Они несут какой-то функционал или это что-то типа сетки для того чтобы ориентироваться при рисовании. Если функционал то интересно как сделать что-то в таком духе.

2. Вот с программным разрезанием на куски вообще туго:) Я пока пытался выводить только те символы которые видно на экране и удалять, которые не видно, но это не тот метод. А какими методами можно разрезать полотно? Я так полагаю что это что-то типа shape и иже с ними?

Александ
24 Октября 2010
— 22:50
#

хм. у меня максимальный размер холста символа по x равен 6375px.
но если увеличить размер сцены до предельного,
то увеличивается до 8000. ? так в cs4 и cs5.

?ван
6 Ноября 2010
— 22:36
#

?гра сделана на Box2d? Просто нашел код под игру вида Mining Truck а что с ним делать ума не приложу. Box2d ведь не может из кода отображать объекты?

Кирилл
8 Декабря 2010
— 17:14
#

А вот за видео спасибо - много проясняет!

pavezlo
11 Апреля 2011
— 22:51
#

Добрый день. С большим удовольствием читаю ваш блог. До сего момента не оставлял комментариев, так как в тех вопросах был не силен.
Как Вы писали, что для оптимизации на сцену добавляются лишь те куски, которые попали в область видимости. Для сильных компьютеров, это не составит труда, но стареньких, такой подход может вызвать проблемы. Это связано с тем что создание и удаление объектов довольно затратно для Flash и обычно, чтобы не возникало лагов в середине уровня, создание и добавление на сцену делается при инициализации уровня. А куски карты, не попавшие в область видимости, просто не отображаются (visible = false).
PS: лично на моем компьютере лагов замечено не было.

freem.trg
13 Февраля 2012
— 09:30
#

@freem.trg
Вы не верно понимаете смысл слова "добавляются". Ничего не создается коммандой new, особенно учитывая, что во флеше удалить объект немедленно - нельзя.
?спользование для этой цели флага visible очевидно.

BuxomBerry
13 Февраля 2012
— 09:40
#

@BuxomBerry
Про то, что нельзя удалить что-то немедленно и как работает gc я знаю. Дело в том, что при прочтении слова "добавляются", первое что пришло на ум (субъективно для меня) это addChild.
То, что под этим словом подразумевался флаг visible для меня оказалось не очевидно.

freem.trg
13 Февраля 2012
— 10:25
#

@freem.trg, visible = false только от части может решить проблему производительности, так как когда объект невидим он только не рендерится, но при этом он как и раньше получает все события и продолжает обрабатываться. Поэтому удаление и добавление объекта с использованием addChild(), removeChild() для статических объектов или тайлов, будет более оптимальным решением.

Ant.Karlov
13 Февраля 2012
— 13:43
#

@Ant.Karlov, вообще статику и уж тем более тайлы, нужно рисовать процедурно в экранный буфер и обновлять этот буфер только по мере надобности (желательно сохраняя при этом не изменившуюся область). Ни о каких addChild, removeChild тут вообще речи не идет.

BuxomBerry
14 Февраля 2012
— 12:17
#

Привет!
Правильно ли я понял, динамически подгружается только визуальная часть(битмапы из массива), а все физические объекты создаются сразу при старте игры?

p.s. Как увеличить область во Flash CS5? У меня ограничено 3510 в одну сторону

airomagic
2 Мая 2012
— 17:53
#

Привет
Вопрос: Вот вы делали пустышки для физики.....а как потом вот эти пустышки связать с объектами box2d..чтобы можно было по ним двигаться??

Ruslan
27 Марта 2013
— 02:27
#

Привет.
А Вы не подскажете как сделать физику машины как в mining truck? Вид сбоку, езда по холмам. мой email brodyj518@gmail.com

Kirya
10 Октября 2014
— 17:34
#