Существует не так много специализированных фреймворков, ускоряющих разработку флеш игр. Из тех что на слуху, можно отметить следующие:
Flixel
FlashPunk
Citrus Engine
PushButton Engine
Этим постом я хочу обратить внимание коллег-флешеров на перспективный опенсорсный движок под названием PushButton Engine. PBE уже успели представить на Adobe Max 2010 и разработать на нем #2 Top Facebook game 2010 по версии insidefacebook.com. Его используют для разработки игр такие компании как Zynga, Playdom, Hive7.
Разработчиками движка являются достаточно известные в геймдевелоперских кругах люди, создавшие такие игры как The Incredible Machines, Tribes, Torque и другие.
Предлагается любопытный компонентный подход к разработке, который, по заверениям авторов, гораздо удобнее и продуктивнее при разработке игр чем традиционный объектно-ориентированный.
Некоторые из возможностей движка:
- Компонентная модель разработки
- Менеджер игровых ресурсов
- Глобально адресуемые объекты
- Физика (средствами Box2D)
- Возможность легкой интеграции с любыми сторонними библиотеками
- Готовые геймплейные компоненты: конечные автоматы, команды, здоровье
- Библиотека нахождения пути
- Рендеринг на основе спрайт-листов и стандартный через спрайты/мувиклипы
- Ускорение/замедление игрового времени, пауза
- Менеджер звуков и музыки
- Логер
- Консоль
- Профайлер
- Менеджер игровых экранов
Урок 1
Урок 2
Урок 3
Урок 4
Что же, будем исправлять ситуацию. В этой вводной статье я расскажу как разработчики PushButton Engine обосновывают предлагаемый ими компонентный подход, что из себя представляют компоненты, как и зачем их использовать.
Что не так с наследованием?
Не всегда объектно-ориентированый работает на благо. При разработке игр часто возникают ситуации вроде описанной ниже.
Предположим, мы создали класс, представляющий игрока.
Далее, мы добавляем класс Предмет и выносим общую функциональность в родительский класс ИгроваяСущность:
Игра растет, сложность иерархий классов растет вместе с ней, но пока все выглядит хорошо.
Но рано или поздно начинают возникать неприятные вопросы. Например, от кого унаследовать класс ДвигающийсяПредмет, от класса Предмет или же от класса МожетДвигаться?
Чаще всего, какой бы вариант мы не выбрали, в итоге мы приходим к чрезмерно раздутому базовому классу со множеством разрозненных методов, которые вызываются наследниками.
Код становится тяжело отлаживать, модифицировать и сопровождать.
Какое решение предлагается?
Выходом в данной ситуации может послужить композиция — разбиение игры на логические сущности, которые заполняются необходимыми компонентами. Например, у нас есть 3 сущности: Игрок, Враг и Предмет.
Используя компоненты, мы как из конструктора формируем сущности:
При таком подходе код становится более понятным и логичным, а единожды написанные компоненты могут быть повторно использованы в других играх.
Данный подход не отменяет наследование, но оно используется там, где действительно подходит, например для иерархий компонентов:
Как компонентный подход реализован в PushButton Engine?
Код, касающийся создания компонентов находится в пакете
com.pblabs.engine.entity.*
Сущность представляет собой легковесный контейнер типа
Entity
, реализующий интерфейс IEntity
. Для создания используем фабричный метод allocateEntity
:var myEntity:IEntity = PBE.allocateEntity();
Проинициализируем созданную сущность, присваивая ей имя, по которому мы сможем позже ее найти в любой точке нашего кода:
myEntity.initialize("MyEntity");
Готово. Осталось наполнить ее необходимыми компонентами, либо предоставляемыми самим фреймворком, либо самописными.
Компонент всегда должен реализовать интерфейс
IEntityComponent
либо напрямую, либо косвенно, унаследовавшись от класса EntityComponent
или его потомков.Создав и настроив экземпляр компонента, добавляем его в сущность, используя метод
addComponent
:myEntity.addComponent(myComponent, "MyComponent");
Как вы уже, наверное, обратили внимание, каждой сущности или компоненту назначается строковое имя. Это необходимо для того, чтобы в любом месте кода мы могли их получить с помощью специальных lookup-методов:
PBE.lookupEntity
PBE.lookupComponentByName
На этом вводная статья о PushButton Engine закончена, а следующая статья будет посвещена внутренней архитектуре фреймворка.