Пример редактора уровней

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

Пример простейшего редактора уровней на основе игры "Грибник". В панели справа выбираем объект и устанавливаем его кликая в сетку. Чтобы удалить объект, нужно кликнуть повторно.

Любая игра, как правило, делится на несколько частей (классов). В моем случае структура игры будет выглядеть следующим образом:

  • Основное приложение — точка входа в игру;
  • ?гровой класс — в нем будут реализованы все игровые экраны и сама игра;
  • Класс редактора уровней — в нем будут использоваться все необходимые классы инструментов для редактирования уровней;
  • Класс игровой карты — это сердце игры и редактора уровней. В нем будет осуществляться управление всеми объектами.

Для редактора уровней нам понадобятся вспомогательные классы:

  • Панель инструментов — объединяет в себе все игровые объекты, которые можно выбирать и после этого устанавливать на игровой карте;
  • Отладочная сетка — этот класс будет отображать игровую сетку для наглядности;
  • Кисть — это простой класс, который будет хранить в себе всю информацию о выбранном объекте через панель инструментов, и через него эта информация будет передаваться в игровую карту.

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

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

Структура

Для наглядности, так выглядит структура папок и классов будущей игры и редактора.

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

Скачать исходники для Flash CS4 .zip — 230 кб

Скачать исходники для Flash CS3 .zip — 180 кб

Далее описание классов:

App.as - основное приложение

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

Game.as - игра

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

LevelEditor.as - редактор уровней

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

В строке 22 мы создаем игровую карту. В качестве первого параметра для игровой карты указываем ссылку на основной класс приложения — это нужно, чтобы иметь доступ к координатам мыши. А вторым параметром мы указываем, что игровая карта должна работать в режиме редактирования.

В строке 26 мы дополнительно создаем панель инструментов, которая будет использоваться как палитра игровых объектов. А так же устанавливаем слушатель на наше пользовательское событие BRUSH_UPDATE — обновление кисточки. Данное событие будет происходить когда пользователь что-то выбирает в панели инструментов. Оно необходимо, чтобы сообщить игровой карте, что параметры кисти изменились. Сообщаем об этом мы игровой карте в строке 53, копируя значения кисти панели инструментов в кисть игровой карты.

ToolBar.as - панель инструментов

В данном классе мы первым делом создаем фон и масштабируем его, чтобы визуально объединить все кнопки. Так же в строках 46-52 мы создаем спрайт — рамку, которая будет подсвечивать выбранный объект в палитре. А в строках 63-64 маленький бонус, благодаря этому коду панель можно таскать по экрану. Методом createButtons() в строке 56 мы создаем все объекты-кнопки, которые пользователь сможет устанавливать на игровую карту и методом orderButtons() в строке 87 красиво расставляем и масштабируем все созданные объекты-кнопочки, а также вешаем на них перехватчик клика мышкой. Код перехватчика клика очень простой, в строке 129 мы лишь копируем все параметры объекта в кисточку и создаем событие, извещающее  о том, что кисть обновилась. Так же при клике на объект в панели инструментов устанавливаем на его место выделение, которое «подсвечивает» выбранный объект.

Brush.as - кисть

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

У класса кисти всего несколько методов, которые позволяют копировать информацию из другой кисти, а так же копировать информацию из указанного объекта. Кроме того кисть хранит в себе координаты тайла, в который устанавливается объект.

Grid.as - сетка

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

Постепенно подходим к самому интересному. Теперь рассмотрим классы игровых объектов. А начнем с базового класса игровых объектов, который будет для всех объектов родителем: 

MapObject.as - базовый класс игровых объектов

Как я уже писал выше, это лишь болванка, которая содержит общие для всех методы, выполняющие похожие функции, а так же методы пустышки, которые в потомках будут перекрываться собственными методами.

В текущей версии базового класса объектов содержится несколько переменных, которые являются общими для всех потомков.  Это: тип объекта, разновидность объекта, положение объекта в тайлах и ссылка на игровую карту, на которой находится объект. По настоящему ценный метод в данном классе только setToPos() в строке 33. Он устанавливает объект в указанную клеточку. Объект устанавливается, выравнивается по центру клетки.

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

Rock.as - игровой объект скала

Этот класс является потомком класса MapObject. Если разглядеть данный класс внимательно, то можно наглядно увидеть, как базовый класс MapObject упрощает всем игровым объектам их существование.

При создании скалы в строках 22-23 мы указываем тип объекта по умолчанию и его разновидность, а так же создаем спрайт в строках 26-28.

В строках 38-41 метод setToPos() перекрывает родительский метод, добавляя дополнительный код, который облегчит нам задачу с установкой скал. Метод updateChessOrder() — устанавливает скалы в шахматном порядке, за счет чего получается интересная фактура, о которой я писал ранее. Достигается этот эффект достаточно просто. При установке скалы мы выполняем проверку - в четной или не четной клеточке находится скала. Если в четной, то меняем кадр, если в нечетной, то ничего не меняем.

А теперь самое интересное.

GameMap.as - игровая карта.

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

Для упрощения всех расчетов в константах указаны: размер игровой клетки, половина клетки, а также размеры игровой карты по высоте и ширине в строках 17-20.

?гровая карта может находится в двух режимах: игровой режим и режим редактирования. От режимов зависит - какие методы для обработки тех или иных действий мы будем применять. Так же в зависимости от выбранного режима можно производить различные оптимизации. Режим карты определяется при ее создании и в далее уже не может быть изменен (в данном примере). Режим хранится в переменной _editorMode, а указывается при создании игровой карты.

Если включен режим редактирования (_editorMode = true), то мы создаем дополнительный слой и спрайт, который подсвечивает клетку, над которой находится курсор мыши.  А так же вешаем на событие ENTER_FRAME обработчик для редактора уровней, который будет производить расчеты только для редактора уровней. В примере не приведен пример игрового режима (_editorMode = false), но по идее в таком режиме не нужно создавать объекты, предназначенные только для редактора. Впрочем, если в примере при создании карты вторым параметром указать false, то можно будет увидеть пустой экран, который говорит только о том, что игры как таковой еще нет :)

Для создания и очистки массива ячеек игровой карты существует метод clear(). В нем мы создаем основной массив _cells[], после чего через циклы заполняем его другими массивами. В следствии чего получаем двумерный массив с пустыми ячейками, к которым можно обратится следующим образом: _cells[row][col]. В данном примере в каждой ячейке может хранится только один игровой объект — но по идее в игре, в каждой ячейке может быть несколько объектов. Я упростил этот момент, чтобы сделать пример редактора менее запутанным и более понятным. Чтобы в каждой ячейке хранить несколько объектов необходимо сделать трехмерный массив ;)

На саму карту в строке 56 мы устанавливаем перехватчик мыши. Его код достаточно прост, в нем мы вызываем метод setObject() с координатами текущего тайла. Координаты текущего тайла, над которым находится курсор мыши, вычисляются через get методы tileX и tileY

В методе setObject() в строке 100 сохраняем координаты в кисть и в зависимости от типа объекта вызываем соответствующий метод. Методы для создания объектов очень похожи, но в примере я их разделил, так как в будущем если добавлять множество разных типов объектов, то для них необходимо указывать индивидуальные параметры.

Редактор сделан по типу: если ячейка свободна, то устанавливаем туда объект, а если занята - удаляем объект - признаться очень удобный подход :) Не нужно постоянно выбирать объект в панели инструментов, чтобы поставить, а чтобы удалить выбирать ластик, а потом снова какой-нибудь объект. Когда работаешь над уровнями приходится много кликать и порой промахиваешься или ставишь объекты неверно и переключения на ластик - вызывает раздражение и отвлекает от работы. Поэтому в каждом методе создания нового объекта выполняется проверка на занятость ячейки, и если ячейка занята то объект удаляется из ячейки, а если свободна - то создается и устанавливается новый. Посмотреть реализацию можно в методе setRock() строка 143 или setTurf() строка 169.

Вот и вся основа простому редактору уровней.

Текущая версия редактора для игры Грибник

А так выглядит текущая версия редактора для игры "Грибник". Графические вариации объектов выбираются случайным образом в момент установки объекта на карту, поэтому всех вариантов объектов нет в панели инструментов.

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

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

Далее по теме: Скроллинг игрового мира. ?ли как реализовать прокрутку карты?

 

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

Ant.Hanumanes
5 Сентября 2009
— 19:14
#

@Ant.Hanumanes, получилось так, что запись опубликовалась раньше чем я успел ее закончить, так что ты видел еще черновой вариант ;)

По поводу теней, бликов и оттенков, к сожалению одним комментарием не описать даже простых основ. Если очень интересно, то постараюсь в следующий раз рассказать про основы рисования.

Ant.Karlov
5 Сентября 2009
— 23:16
#

очень очень приочень интересно уже как год наверно!!! Но пока чудо приёмы не найдены, и всё делаю методом тыка или копипаста).
Буду очень багодарен за такой пост, если чем то смогу помочь - то буду рад стараться (например можно взять какого -то персонажа и разукрасить его вдвоём [я по чайниковски, а вы по стандарту] и выделить ошибки начинающих художников и тд и тп)

Ant.Hanumanes
6 Сентября 2009
— 11:24
#

Вполне ничего редактор выходит. Только я бы еще сделал так, чтобы объекты можно было вставлять зажав кнопку мыши и водя по экрану, а то для больших карт запаришся кликать.
Флашка к сожалению не открылась -- наверно, это CS4?
А вообще, блог классный, удачи!

Roman
7 Сентября 2009
— 12:11
#

+1
было бы тоже очень интересно и познавательно иметь под рукой такой урок

LegendMAN
7 Сентября 2009
— 12:43
#

@Roman, сделать рисование мышкой как кистью довольно просто. Только в представленном примере размер ячеек настолько велик что мышкой особо не порисуешь :)

Обновил запись, добавил исходники сохраненные для CS3.

Ant.Karlov
8 Сентября 2009
— 01:06
#

Сейчас, чтобы заполнить какую-то область одинаковыми элементами нужно по каждой клетке кликнуть, а хотелось бы, чтобы можно было зажать кнопку над какой-то ячейкой (она сразу же заполняеться выбранным элементом) и провести мышкой над теми ячейками, кторые хочется заполнить. Вот...
?сходники скачались, открылись и откомпилились! Спасибо.

Roman
8 Сентября 2009
— 11:24
#

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

shaman4d
19 Января 2010
— 17:48
#

Антон будь так добр, перезалей исходники для CS3

Lost
13 Марта 2010
— 22:59
#

Привет и спасибо!

а что на выходе? - как сохраняется сама карта? ХМL?

Андрей
19 Мая 2010
— 13:27
#

@Андрей, о способе хранения уровней в игре я хотел написать отдельно, но так и не сложилось пока к сожалению. По идеи на выходе можно сделать любой удобный для себя способ, достаточно лишь при сохранении перебрать массив с объектами и сохранить/вывести в output все параметры объектов которые важны для их создания.

Ant.Karlov
5 Июня 2010
— 07:33
#

Так как не было написано ничего расскажите что вы использовали для хранения карты? Массив? XML или текстовый файл который потом в проект зашили?

Я не робот!
6 Октября 2010
— 09:15
#

@Я не робот!, для хранения карты использовал массив который потом просто вставлял в код класса уровня. Так же можно использовать XML — он удобнее, но его чтение занимает больше времени. В уроках о TD будет об этом рассказано.

Ant.Karlov
6 Октября 2010
— 23:44
#

Спасибо!

Я не робот!
7 Октября 2010
— 11:53
#

Спасибо! Вы бы еще в свободное время написали статью о том как сохранять и загружать данные редактора в файл!

Василий
15 Ноября 2010
— 03:10
#

привет. Пытаюсь сделать как у Вас, Выходит ошибка : "1119: Обращение возможного неопределенного свойства debugInfo через ссылку со статическим типом com.disobedientchild:LevelEditor ." в файле App.as строка 69.

Кен
17 Ноября 2010
— 14:08
#

Вопрос о том, как реализовать повтор игры?
Т.е. чтобы после окончания уровня можно было посмотреть как ты играл этот уровень.
?нтересны все идеи. В Сети ничего не удалось найти.
Если есть какие-нибудь соображения пишите на
yusrom@gmail.com
? спасибо Антону Карлову за этот блог.

yusrom
24 Ноября 2010
— 21:17
#

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

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

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

Ant.Karlov
26 Ноября 2010
— 03:00
#

ui_toolbar_bg

У меня проблемы.
Непонятная строчка. Откуда взялся такой класс?

ui_toolbar_bg
6 Февраля 2011
— 01:37
#

@ui_toolbar_bg, «ui_toolbar_bg» — это обычный клип с изображением фона для панели инструментов в библиотеки клипов.

Ant.Karlov
6 Февраля 2011
— 17:39
#

@Ant.Karlov, да, спасибо) Я разобрался сразу после того как написал вопрос. Просто не привык, что этот класс нигде не объявлен кроме библиотеки клипов.

ui_toolbar_bg
7 Февраля 2011
— 12:21
#

Антон, спасибо еще раз. Хочу уточнить еще одну вещь. Константы типов объектов выделены в отдельный класс ObjType. А не проще и оптимальнее будет эти константы поместить в базовом классе MapObject? ?ли здесь есть какая-то задумка на будущее?

ui_toolbar_bg
9 Февраля 2011
— 23:35
#

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

Ant.Karlov
14 Февраля 2011
— 02:58
#

Попытался добавить объект камень (в CS4) по образу и подобию уже существующих объектов. Открывается плеер. Ничего кроме белого фона и ошибки 1180: Вызов предположительно неопределенного метода sprite_Stone
.

Xel
3 Мая 2011
— 23:05
#

Читаю только вас и Xitri. Насчет авторского стиля - Тут кто-то вначале писал, что урок бы по вашему стилю рисования ,был бы очень кстати,и еще, на xitri графика удивительно схожа с вашей, вы из одной школы флэш-художников ? :))

Константин
28 Июня 2011
— 16:18
#

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

mirashic
1 Апреля 2012
— 21:40
#

Отличный урок! Однако, столкнулся с достаточно глупой проблемой. Хотел реализовать возможность скролить редактор клавишами, но по не понятным мне причинам скрипт о котором писали здесь в уроке посвященному скролингу не смог пошевелить карту уровня (хотя все компилировалось). Помогите решить проблему, напишите пару строчек кода, тк правда очень нужно! Заранее огромное спасибо!

B2
5 Ноября 2012
— 12:58
#

Попробовал реализовать способ сохранять уровни из редактора как в уроке про TowerDefence #6, но столкнулся с проблемой!

Там мы вызываем массив mapMask

private function exportToOutput():void
{ var mapMask:Array = _universe.mapMask;

Попробовал сделать по подобию так же в LevelEditor

private function exportToOutput():void
{ var mapMask:Array = _gameMap.cells;

Пишет ошибку: обращение возможно неопределенного свойства cells

В чем беда?

Макс
5 Ноября 2012
— 18:18
#

Попробовал реализовать сохранение карты в массив, как в уроке TD, в итоге на выходе в output я получаю перебранный массив вида:
_cells = [
[ 0, 0, 0, [objecxt Rock], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
Далее копирую его и вставляю в класс level1. Появляется ошибка:
1084 Синтаксическая ошибка (rightbracket перед Rock).
Друзья, подскажите в чем беда?

error
23 Ноября 2012
— 23:35
#

Помогите пожалуйста!

error
24 Ноября 2012
— 00:08
#

Привет Антон! А как ты реализовал метод который ставит объект на карту, который занимает сразу несколько клеток?

Nick
25 Ноября 2012
— 13:29
#

Друзья, кто ни будь вообще реализовывал что ни будь подобное?
Просто уже давно мучаюсь из-за ошибки, help! =(

error
26 Ноября 2012
— 23:14
#

@error, при экспорте уровня в output указан объект, а не атрибут объекта, поэтому в место ожидаемой цифры с типом объекта (или обозначением что клетка занята) вы получаете в массиве:

[object Rock]

Если вы это прямо так и вставляете в код, то это конечно же порождает синтаксическую ошибку.

Ant.Karlov
27 Ноября 2012
— 00:02
#

@Nick, если рассматривать пример с Грибником, то установка объекта размером больше одной клетки реализована таким же образом как и установка маленьких объектов. То есть размер объекта не имеет значения.

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

Ant.Karlov
27 Ноября 2012
— 00:04
#

Антон, спасибо огромное за ответ! В этом и проблема, что я не могу понять как правильно выводить атрибуты объекта в массив. Если я правильно понимаю, то [object Rock] содержит в себе: тип, вариацию и координаты на карте? Пожалуйста, можешь написать пример как вывести их в код? =(

error
27 Ноября 2012
— 02:14
#

Просто не совсем понятно как синтаксически это должно выглядеть

error
27 Ноября 2012
— 02:15
#

@error, выводить так же как и любую другую информацию в trace:

trace(myObject.type, myObject.x, myObject.y);

Чтобы в окне output отобразилось нечто похожее на код который бы можно было сразу вставить в код игры, то вывод надо отформатировать соответствующим образом, например:

trace("[" + myObject.type ", " + myObject.x + ", " + myObject.y + "]");

Ant.Karlov
27 Ноября 2012
— 03:48
#

Спасибо! На самом деле я вывел в trace эти данные (3 значения соответственно), и соответственно вставил их в массив _cells (класс level1) на место где был [object Rock]. Получилось что-то вроде:
[ [0, 32, 32] 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], .....
Откомпилировал, но на карте ни чего не изменилось. Хэлп!

P.S Антон, спасибо большое за то, что на сайте реализованы комменты, а то даже не у кого спросить =(

error
29 Ноября 2012
— 01:41
#

Очень трудно орентироваться в коде, если в тексте статьи его нет. ссылки на строки намного труднее воспринимаются. лучше вставлять фрагменты кода в текст урока. Тем более если у читывать что не у всех он откроется и скомпилируется. ( у меня flashdevelop, так там код похожий, но вот исходники нужно допилить сильно чтоб запустить).

BolT
29 Ноября 2012
— 13:40
#

Может быть в классе Level1 можно как то сделать некоторого рода ссылку на [object Rock], чтобы при считывании данных из массива _cells на их месте появлялся объект скала. Если это возможно то как это можно реализовать?
В каком виде вообще можно вводить атрибуты данного объекта в массив?

error
30 Ноября 2012
— 16:32
#

@Ant.Karlov, перепробовал разные варианты, но все ровно не могу загрузить level1 в leveleditor, проверил массив грузит все как надо. Но не знаю как в массиве который находится в классе Level1 прописать необходимые объекты. Очень странно.
Буду очень признателен если поможете разобраться :(

error
2 Декабря 2012
— 15:25
#

@Ant.Karlov очень извиняюсь за то, что ворую ваше время, но правда очень хочу разобраться с этим вопросом. Немного переформулирую свою проблему и вопрос: мой проект в режиме редактора отлично грузит массив из класса level1 заполненный нулями. Я долго и тщетно пытался вбить в него параметры объекта Rock в виде о котором писалось выше, но это не помогло. Попробовал сделать метку в ячейке массива _cells но не совсем понятно как и где ее определить. Так же у меня возникает вопрос. Появление нового объекта в массиве насколько мне понятно должно вызывать собой функции:
setObject(1,1)
setRock();
А для их определения придется еще раз заново перебирать массив? (хотя в уроке редактора TD насколько я помню мы такого не делали). В общем очень надеюсь что суть вопроса понятна (если не могу скинуть исходники своего проекта, но не думаю что у вас есть на это время :)
Пожалуйста раскройте глаза на истину, а то уже неделю кручусь вокруг да около =) Заранее большое человеческое спасибо.

error
4 Декабря 2012
— 16:19
#

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

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

Ant.Karlov
5 Декабря 2012
— 01:04
#

Спасибо за ответ! Но даже почитав статьи по классам и массивам я прихожу к выводу что придется реализовать что-то вроде подобного кода:
(за 1 взят обьект рок)
for (var ay:int = 0; ay < cellsH; ay++)
{ for (var ax:int = 0; ax < cellsW; ax++) {
if (cells[ax][ay] == 1) {
_layerMain.addChild(r);
r.setToPos(ay,ax);
trace("1");
}
}
}
return _cells;
}

Печально это.

error
10 Декабря 2012
— 23:42
#

@Ant.Karlov дико извиняюсь и больше не буду донимать вас своими примитивными вопросами :)

error
10 Декабря 2012
— 23:44
#

@error, отлично! Я рад, что вы подошли к вопросу серьезно и разобрались с основами. Теперь я вам уже конкретно и по существу могу посоветовать отказаться от хранения уровней в двухмерном массиве и использовать для этого обычный массив как список всех объектов расположенных на уровне в котором бы хранилась информация:

1. Вид объекта (камень, бонус и т.п.);
2. Разновидность объекта (если существует несколько видов бонусов, например);
3. Расположение объекта на карте (например в клетках, но можно и в реальных координатах если возможно неточное расположение объекта).
4. и т.п. если необходимо.

Далее вы просто перебираете весь такой список и создаете объекты исходя из информации в нем ;) ?спользуя обычный список вам не придется хранить информацию о пустых ячейках на карте, а так же вы можете легко добавлять новые параметры и объекты. То есть если вам придется добавить в игру какой-то объект который должен хранить о себе больше информации чем все остальные объекты, то вам не составит труда добавить его поддержку при сохранении и загрузки карты.

Ant.Karlov
11 Декабря 2012
— 01:51
#

Спасибо еще раз! :) В общем я поступил следующим образом:
в классе GameMap объявил переменную нового массива для хранения всего этого:
public var saveCells:Array = [];
Далее в публичной функции setRock() реализовал заполнение этого массива новой записью при каждом добавлении объекта Rock на карту:
saveCells.push("["+"ROCK", r.x, r.y, r.type, brush.variety+"]");
Соответственно при создании скал на карте в массиве для каждой будут записаны: Метка объекта "ROCK", положение, разновидность и т.п
Допустим получившийся массив был положен в класс Level1, откуда его можно загрузить при загрузке уровня.

А вот далее возникает небольшое затруднение, а вернее вопрос. Как мне реализовать перебор такого вот списка, чтобы из полученных данных можно было воспользоваться функциями
setObject(a,b);
setRock(); и т.п
Вопрос скорее поставлю так: как перебрать этот список так, чтобы после каждой метки ROCK брать с массива данные для создания объекта на карте.

Прошу не злиться на такие вот глупости :) Спасибо.

error
21 Декабря 2012
— 01:34
#

@error, вам не нужно записывать каких либо дополнительных меток. Просто записывайте самым первым атрибутом непосредственно тип объекта, так как по нему можно будет определить что за объект тут сохранен и какие данные необходимо считать. Например у вас есть список такого формата:

[type, variety, x, y]

Который в заполненном виде может выглядеть так:

var levelData:Array = [
[1, 1, 12, 34],
[1, 2, 567, 344]
];

Далее чтобы считать информацию из такого массива, ваш код может выглядеть следующим образом:

var record:Array;
for (var i:int = 0; i < levelData.length; i++)
{
record = levelData[i];
switch (record[0]) // type
{
case 1 : // Rock
makeRock(record[1], record[2], record[3]);
break;

case 2 : // Tree for example
makeTree(record[1], record[2], record[3]);
break;
}
}

Чтобы не хранить большую ирархию массивов непосредственно в коде (не создавать много массивов при запуске программы), можно хранить данные в строках формата "type,kind,x,y":

var levelData:Array = [
"1,1,12,34",
"1, 2, 567, 344" ];

А при переборе массива с данными преобразовывать их в массивы налету методом split():

var record:Array = levelData[i].split(",");

Ant.Karlov
21 Декабря 2012
— 02:20
#

Если я все правильно понял, то:
В классе GameMap создал массив:
public var saveCells:Array;

В классе LevelEditor`a создал:
public function LoadClickHandler(event:MouseEvent):void
{
trace(_gameMap.saveCells);

var record:Array;
for (var i:int = 0; i < _gameMap.saveCells.length; i++)
{
record = _gameMap.saveCells[i];
switch (record[0]) // type
{
case 1 : // Rock
trace("rock is coming");
break;
}
}
}

А в классе Level1 добавил:
_gameMap.saveCells =
[1,0,224,160];

Но при нажатии на кнопку Load в редакторе в output появляется:

TypeError: Error #1034: Ошибка типа Coercion: невозможно преобразовать 1 в Array.
at com.mushroomer_example::LevelEditor/LoadClickHandler()

Дайте совет пожалуйста =(

error
28 Декабря 2012
— 17:04
#

@error, ошибка здесь:

record = _gameMap.saveCells[i];
switch (record[0]) // type


В переменной record число (int или number), а вы с ним пытаетесь работать как с массивом. Если конечно я правильно понял описание ошибки. Проверяйте.

Ant.Karlov
28 Декабря 2012
— 19:33
#

В принципе заработало, но пока без split`a :) Антон спасибо огромное за подробные ответы и полезные статьи! ? кстати с наступающим! :)

error
31 Декабря 2012
— 12:59
#

Реклама БЕС?Т!!!

Антя
1 Февраля 2013
— 08:42
#