Редактор на основе Flash IDE : Компоненты.

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

Давайте попробуем создать компонент.
— Нам потребуется создать MovieClip
— В библиотеке кликаем правой кнопкой по нашему клипу и жмем Component Definition
ComponentDefinition
В списке Parameters добавляем нужные нам параметры
Name — имя видимое в компоненте
Variable — переменная будет объявлена в классе TestComponent
Value — значение по умолчанию
Type — тип, типов предостаточно чтоб описать любые свойства.

Class — TestComponent.as класс в котором мы и реализуем работу компонента.

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

Когда мы перетащим компонент на сцену то увидим на панели Properties такую картину
ComponentTest
Ура теперь мы можем редактировать эти свойства прямо на сцене! Но это еще не все, чтоб мы могли с ним работать программно нам нужно написать наш TestComponent.as, выглядеть он будет так
package 
{
        public class TestComponent
        {
                [Inspectable(type="String", defaultValue="")]
                public var name:String = "";
                
                [Inspectable(type="Number", defaultValue="0")]
                public var param1:Number = 0;
                
                [Inspectable(type = "Boolean", defaultValue = "false")]
                public var param2:Boolean = false;
                
                public function TestComponent():void{}
        }
        
}
Вот теперь мы сможем настроить этот компонент в IDE и считать данные при выполнении программы.
В итоге нам нужно написать парсер мувиклипа уровня как и упоминаемой выше статье, но когда мы натыкаемся на компонент мы получаем значительно больше нужной нам информации нежели при работе с простым мувиклипом.

А теперь попробуем создать простенький редактор для физической игры (для физики мы используем Napе).
1) Создадим компоненту для настройки мира
ComponentTest
Для базовой настройки свойств физического мира этих параметров вполне достаточно, гравитация и границы.

2)Физическое тело, список параметров тут немного поинтересней
ComponentShim
Статическое ли тело / материал / тип объекта /начальные скорости
Класс выглядит так

public class PhysShim extends Sprite
{
        // physic props
        protected var _material:String = "none";
        protected var _shapeType:String = "none";
        protected var _isStatic:Boolean = false;
        protected var _vel_x:Number = 0;
        protected var _vel_y:Number = 0;
        protected var _vel_w:Number = 0;
        
        protected var _type:String = "none";
        
        public function PhysShim()
        {
                super();
                trace("PhysShim:PhysShim->");
        }
        
        public function get shapeType():String { return _shapeType; }
        public function set shapeType(value:String):void
        {
                _shapeType = value;
        }
        
        public function get material():String { return _material; }
        [Inspectable(type="List", enumeration="none,wood,ice,stone,ground,metall,snow,bounce", defaultValue="none")]
        public function set material(value:String):void
        {
                _material = value;
        }
        
        public function get isStatic():Boolean { return _isStatic; }
        [Inspectable(type="Boolean", defaultValue="false")]
        public function set isStatic(value:Boolean):void
        {
                _isStatic = value;
        }
        
        public function get vel_x():Number { return _vel_x; }
        [Inspectable(type="Number", defaultValue="0")]
        public function set vel_x(value:Number):void
        {
                _vel_x = value;
                trace("PhysShim:vel_x->",vel_x);
        }
        
        public function get vel_y():Number { return _vel_y; }
        [Inspectable(type="Number", defaultValue="0")]
        public function set vel_y(value:Number):void
        {
                _vel_y = value;
        }
        
        public function get vel_w():Number { return _vel_w; }
        [Inspectable(type="Number", defaultValue="0")]
        public function set vel_w(value:Number):void
        {
                _vel_w = value;
        }
        

        public function get type():String { return _type; }
        [Inspectable(type="List", enumeration="none,bullet,target", defaultValue="none")]
        public function set type(value:String):void
        {
                _type = value;
        }
        
}

По коду видно как использовать и задавать списки. Один параметр не возможно задать в компоненте это _shapeType — тип шейпа (прямоугольник / круг / овал / треугольник / любая форма), это сделано для того что дальше мы создаем для каждого типа шейпа свой компонент и задаем значение _shapeType явно. Для примера Круг:

public class CircleShim extends PhysShim
{
                
        public function CircleShim()
        {
                super();
                _shapeType = ShapeType.CIRCLE;
        }
                
}

Выглядят наши физические компоненты на сцене приерно так, и каждый обладает перечисленными свойствами
ComponentShims
ShimProps
Строится игровой объект так — создаем обект в которы добавляем и графику и физику, при парсенге физический компонент удаляется после обработки данных.
ShimProps
По такому принципу очень просто сделать набор объектов (у нас тут набор дерева/камня/льда)

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

На видео мало что видно, на самом деле очень просто и удобно.
Такой же подход использует и WCK — просто супер для ленивих физиков :) редактор в Flash IDE.

Комментарии (52)

0
Спасибо, очень полезно...:)
+1
Круто! Спасибо! )))
0
Конечно круто! Ты же делал:)
0
Теперь остаётся только рассказать что такое парсинг и как правильно его делать ^_^
+1
Наверное в простейшем виде как у Антона Карлова, только тут гибче (есть параметры)


var level:MovieClip = new MyGameLevel();
for (var i:int = 0; i < level.numChildren; i++)
{
        if (level.getChildAt(i) is Sprite)
        {
                switch ((level.getChildAt(i) as Sprite).name)
                {
                        case "Box" : 
                                // Создаем физический объект ящик
                        break;
                        case "Barrel" :
                                // Создаем физический объект бочка
                        break;
                        // и т.д. для всех физических объектов
                }
        }
}
0
Примерно так.
0
Если компоненты не связывать с классами, то этот пример годится в таком виде как есть, только в место
(level.getChildAt(i) as Sprite).myVariableName
:)
+1
Расскажем, но немного попозже. В один пост не хорошо было писать.
0
Просим, просим!
+1
Немножко изменю предоставленный код.


var level:MovieClip = new MyGameLevel(); //тащим мувиклип с левелом из библиотеки
for (var i:int = 0; i < level.numChildren; i++)
{
        if (level.getChildAt(i) is Sprite)
        {
                var pObject=level.getChildAt(i);

                switch(GameConstants.GetConstantByName(pObject.Type))
                {
                        case GameConstants.OBJTYPE_DYNAMICBODY : 
                                // Создаем физический объект
                                App.mEngine.addObject(new DynamicBody(pObject));
                        break;
                }
        }
}

public class base_dynamic_object extends main.engine.GameObject implements main.engine.IObject
{
        private avr mSprite:AnimatedSprite;
        private var mBody:PhysBody;     
        ...
        
        public function base_dynamic_object(mc:*)
        {
                super();

                mBody=null;
                
                for(var i=0; i<mc.numChildren; i++){
                        
                        var pObject=mc.getChildAt(i);
                        
                        switch(GameConstants.GetConstantByName(pObject.Type)){
                                
                                case SUBOBJTYPE_ANIMATEDSPRITE:
                                        mSprite=new AnimatedSprite(pObject);
                                break;
                                case SUBOBJTYPE_PHYSOBJECT:
                                        this.addPhysObject(pObject);
                                break;
                        }
                }
                
                if(mBody!=null){
                        mBody.SetXFormScaleless(mc.x, mc.y, mc.angle);
                        setImpulse(mc.velX, mc.velY);
                }
                
                ...
        }
        
        private function addPhysObject(mc):void{
                
                if(mBody==null){
                        mBody=new PhysBody(this);                       
                        mBody.CreateDefinition(10, 10, mc.fixed_rotation);
                }

                mBody.CreateShape(mc, mc.mass, mc.restitution, mc.density, mc.isCircle, mc.isSensor, mc.category_bits, mc.mask_bits, mc.shape_name);
        }
}



Вот наверное как то так. В данном примере описание компонента есть и у самого ресурса (объект который лежит на уровне и ждёт парсинга), и у детей ресурса. Например DynamicBody это комбинация одного анимированного спрайта и многих шейпов внутри него. Например там может быть несколько шейпов для имитации физики и один сенсор для просчета попаданий пуль. Шейпы и спрайт мы вытаскиваем по типу (тоже свойство компонента, но в библиотеке это строка, а здесь берем константу по строке). А вообще всё зависит от архитектуры проекта.
0
Спасибо! Щас буду поковырять.
0
100% нужная штука) +1
0
отличный пост! спасибо. не знал про эту штуку с компонентами. очень удобно. :)
+1
Это действительно хороший и удобный способ когда игровым объектам нужно задавать более чем одно свойство во Flash IDE :) От себя хотелось бы добавить, что компонент не обязательно привязывать к какому-либо классу. Если компонент не будет привязан к классу, то заданные свойства будут привязаны непосредственно к выбранному клипу. Ну и примера парсинга не хватает если уж затронута тема редактора ;)
0
5 баллофф! )
0
Всегда юзал компоненты флеша, но как они создаются руки не доходили. А все оказывается просто, спасибо!
  • adzh
  • adzh
0
А почему в приведённом примере для треугольника физическая компонента изображена как хексагон? А в ролике она как треугольник действует.
0
Хексагон в данном случае — произвольная фигура заданная набором точек по часовой стрелке. Треугольник задан 3-красными точками.
Можно высчитывать точки для треугольника из ширины и высоты, там у нас так же есть такие.

Хексагоном удобно создавать объекты типа
0
Спасибо за ответ. Очень простое и прекрасное решение, мне нравится :)
0
Я так понимаю это дело программно разбивается на конвексные фигуры и создаётся физ. объект?
0
А можете привести пример кода или ткнуть носом, где про это почитать можно? Как обходить точки по кругу? как вы их задаете в редакторе(на отдельном слое или еще как)? Какие классы используете?
+1
По кругу их создавать (в IDE), а потом на основе индексов (глубины расположения) и выстраивается порядок. Главное правило: Более новым объектам присваиваются бОльшие индексы.
+2

private function parsePoints(object:DisplayObjectContainer):GeomPoly
{
        var vertices:Array = [];
        
        while (object.numChildren > 1)
        {
                                
                var obj:DisplayObject = object.removeChildAt(1);
                vertices.push(new Vec2(obj.x*object.scaleX, obj.y*object.scaleY));
        }

        return new GeomPoly(vertices);
}

Проверяю на > 1, потому как на 0 лежит нужный мне объект.
0
Шейпи круг, прямоугольник, хексагон — это только графическое обозначение. Для объектов нестандартной формы было выбрано обозначение хексагоном.
0
Спасибо,
всё никак руки не доходили покопать в этом направлении, а тут всё на блюдечке ))
0
Спасибо! Только странно, я вот создал символ, перетащил на сцену, но у меня не так выглядит Пропетис

А выглядит как и обычно, в котором
position and size
color effect
dysplay
  • J0x
  • J0x
+1
Спасибо!
Тоже пользуюсь IDE в качестве редактора. Параметры и свойства объектов передаю в названиях мувиклипов. Это оч. удобно тем что объекты не привязаны к определеным мувиклипам. Можно создать любой мувик, любой формы и с любым рисунком, в названии указать параметры тела. В игре появится уже готовое тело с определенным рисунком и свойствами!
Про компоненты не знал, буду изучать.
0
Component Parametеrs — не появился у меня
  • J0x
  • J0x
0
Выделив компонент на сцене в свойствах нажми на значок «Component Inspector panel»(иконка компонента)
0
но это немного другое и Component Inspector отличается от Component Parametеrs на сколько я вижу
0
xD
В «Component Inspector» есть вкладка «Component Parameters».
0

типа так? просто я смотрю на ролик и вижу, что там не так.
0
Я использовал Flash CS5. У тебя по ходу CS4, но особой разницы нет, в этом окне и задаешь.
+1
Я вроде как описывал уже эту штуку в блоге у Антона Карлова. Видимо нужна была отдельная статья)) Не подумал)) Писать собственный класс под компонент вообще не тема — тупо убиваем время. Всё что нужно задается прямо через параметры символа в библиотеке, редактируется через шифт+ф7 на сцене. Нужны глобальные константы — пишем парсер стрингов в константы. А вообще есть подозрение что нужно копать в сторону собственного редактора. IDE удобная штука, но ведь приходится после каждой перестановки компилировать проект чтобы посмотреть что вышло. Точнее сначала сохранять, потом компилировать — жрёт время. А с собственным редактором проект можно не трогать вообще. Написать один раз прототипы любых объектов, а дальше сидеть в редакторе всего (и левелов тоже) и собственно творить игровой процесс. Хотя для маленьких проектов это не нужно. А большие не выгодны. Продолжаем юзать IDE!!!
0
Хотя для маленьких проектов это не нужно. А большие не выгодны.
Почему не выгодны?
0
не окупаются. рынок не тот. нужно стараться укладываться в 1-3 месяца. но ничего не мешает потихоньку апдейтить собственный енджин используя его во всех проектах.
0
Как и не что не мешает апдейтить свой универсальный редактор используя его в всех проектах.
+1
Дело в том что «универсальный» не нужен, нужен редактор способный помогать в разработке игрушек определенного типа. Универсальность губит и страшно затягивает разработку.

Насчет потихоньку апдейтить «универсальный» редактор — в определенный момент приходит понимание что не все продумано заранее и что редактор лучше бы вообще переписать с 0 и.т.д…

Конкретная задача (набор однотипных задач) — один специализированный редактор.
ЗЫ: ИМХО
0
Согласен. Универсальный редактор для игр одного жанра.

Просто не согласен, что разработка своего редактора не выгодна.
Плюсы своего редактора:
— нет перекомпиляции.
— возможность делегировать работу по созданию уровней.
— разработка уровней для других платформ. (Тестируем уровень сразу на iPhone. Почему бы и нет?)
0
Я именно про универсальный говорил.

Для конкретных типов задач(игр) да! и однозначно! нужен специализированный редактор:)
Зачастую (зависит от типа задач) можно воспользоватся Flash IDE, так как есть все необходимое и время затраты значительно меньше.
0
Как раз сейчас работаю над своим редактором. Делать свой редактор уровня Flash IDE нет смысла. Неужели всем нужна мощь Flash IDE для разработки уровней?

Интересно услышать мнение камрадов, кто использует свой редактор.
0
Все зависит от конкретной задачи. Много плюсов у обоих вариантов но и минусы имеются.
+2
Игры разные, редакторы разные. Например сейчас делаем тавер дефенс — там редактор уровней это соединенная штука для манипуляции тайлами и построения путей. Делать это внутри Flash IDE — медленная смерть. А вот для физических паззлов IDE вполне хватает. Расставил на глаз, соединил (опять же читаем Антона Карлова) — и понеслась физическая карусель. Действительно просто и удобно. С другой стороны один раз написать по человечески оболочку способную выдавать красивый интерфейс для редактирования любых параметров класса — и иде уже не нужен. Вращение и масштабирование это не проблема. Шустрое добавление новых объектов через поп-ап окошко/возможность на лету протестировать получившийся уровень и прочие пряники — это всё реально. Вопрос только сколько времени займет. Но меня вот такая идея зацепила. Если есть желание можно где нибудь на форуме начать перекидываться мыслями относительно возможной реализации.
0
Можно в персональных блогах
0
Ребят, кто нибудь сталкивался с такой проблемой: задаю значение переменной типа Nubmer через IDE и компоненты, получается такая штука, что в IDE ставлю допустим 0.1, в а коде оказывается, что значение увеличено в 100 раз, т-е вместо 0.1 уже 10, соответственно число меньше 1 выставить нельзя т.к. IDE позволяет выставлять числа только до сотых. Что делать?
0
Попробуй 0,1
0
Что делать?
Купить лицензионную IDE ;)
Или поменять в ОС разделитель по умолчанию на точку.
0
Благодарю =)
0
Ну он автоматически, если я ставлю точку — переводит ее в запятую.
Еще идеи? редактор — CS5 версии.
0
Столкнулся с такой проблемой:
Кидаю на сцену компонент -> компилирую -> код не видит параметры компонента ((level.getChildAt(i) as Sprite).myVariableName = undefined).
Кидаю на сцену компонент -> меняю любой из моих параметров -> компилирую -> компонент обрабатывается нормально, все параметры определены.

(Flash CS4)
0
flashgamedev.ru/viewtopic.php?f=6&t=2783&p=41123
0
Наконец-то собрался разобраться в этом. Спасибо огромное за статью!

Пара уточнений, если кто друг столкнётся с такими же проблемами, как у меня — класс TestComponent надо сделать наследуемым от MovieClip.

В Component Definition параметры можно врчную не добавлять. Если будет готов сначала ас файл, то после прописывания в после Class нашего файла и нажатия ОК, Inspectable параметры подхватятся сами (это можно проверить, зайдя в Component Definition второй раз).

Не забудьте и в свойствах Linkage вашего компонента поставить такой же класс TestComponent.

Парсинг проводите по событию FRAME_CONSTRUCTED
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.