Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 03.03.2019, 01:00   #1
SaiLight
Форумчанин
 
Аватар для SaiLight
 
Регистрация: 10.01.2009
Сообщений: 121
Репутация: 165
Хорошо Galaxy Boom mini: Процесс разработки

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

Оба эти проекта были достаточно тепло восприняты и так же тепло забыты по причине отсутствия обновлений. Но в этой теме, с позволения администрации, я исправлю данную оплошность и постараюсь осветить процесс разработки новой версии Galaxy Boom mini, включающей в себя огромное количество подпроектов. Уже 3 года прошло с момента появления на свет GBM и почти 5 лет теме о графическом движке, но время не было потрачено впустую: все эти годы ушли на подготовку и получение знаний, необходимых для разработки проекта такой сложности. А самому миру Galaxy Boom и всем его основным персонажам уже около 10 лет, но это уже совсем другая история.

Итак, пара слов о том, что планируется в итоге. Сетевая 2D-игра (возможно, с сюжетной кампанией) с роботами, бомбами и интересными, на наш взгляд, геймплейными решениями. Технически: разрабатывается на Delphi XE; сетевая часть, скорее всего, будет написана с использованием библиотеки Synapse и TCP-протокола; сама игра будет реализована с использованием нового для нас ECS (Entity Component System)-шаблона проектирования. Вот некоторые из модулей, включенных в проект, над которыми в данный момент ведется работа:
  • Графический движок Perfect Engine 3 (новая версия).
  • Система 'резинового' графического интерфейса.
  • Менеджер ECS.

Теперь вкратце о каждом из них.

Perfect Engine 3. С момента разработки второй версии движка многое изменилось. Теперь здесь есть полноценный OpenGL-рендер с буферными объектами (против GLBegin/GLEnd в предыдущей версии), рендером в текстуру и шейдерными эффектами. Сам движок стал более структурным, а место кучи callback-функций в нем занял абстрактный рендер со своим набором свойств и методов, от которого и наследуются остальные рендеры.

Система UI. В данный момент, как раз, ведется ее разработка. Это модуль с классами - прототипами будущих элементов графического интерфейса и модуль менеджера UI с управлением сценами, а также, возможностью загрузки интерфейса из json-файла и его стилизации при помощи файла стилей. Для автоматической стилизации компонентов используются методы встроенной библиотеки RTTI.

Менеджер ECS. Набор классов, реализующий взаимодействие между Сущностями, Компонентами и Системами и удобную работу с ними посредством Менеджера событий.

Игра пока находится на самой ранней стадии; разработка продвигается медленно, но верно. Ранее мы не сталкивались ни с сетевыми играми, ни с ECS-шаблоном, и таких крупных проектов до сего момента на себя не брали. В финале первого этапа разработки должна получиться тестовая сетевая игра без графики и геймплея будущей игры, которая даст нам уверенность в правильности выбранных нами инструментов и знания относительно программирования сетевых игр. Уже в рамках разработки этой простой игры мы столкнулись с необходимостью написания ECS и UI-менеджеров, а также, других незначительных модулей. В дальнейшем, за счет правильно построенной структуры, планируется довести этот сырой продукт до полноценной, запланированной нами изначально, игры.

Всех, кому интересен процесс разработки, приглашаю в данную тему. В сообщениях ниже чуть более подробно собираюсь осветить некоторые аспекты уже готовых модулей ну и просто буду стараться не забрасывать эту тему, по возможности, выкладывая обновления и сообщая об основных новостях разработки.
SaiLight вне форума   Ответить с цитированием
Старый 04.03.2019, 18:02   #2
SaiLight
Форумчанин
 
Аватар для SaiLight
 
Регистрация: 10.01.2009
Сообщений: 121
Репутация: 165
По умолчанию



В третьей версии движок Perfect Engine и рендер для него были полностью переписаны, код проекта перенесен на Delphi XE и использует новые возможности языка. В данный момент доступен только OpenGL-рендер, его функциональность, как и функциональность самого движка, сильно расширены. Сейчас Perfect Engine 3 находится на стадии тестирования и доработки.

Изменения коснулись не только основных файлов движка, но и дополнительных модулей и объектов. В частности, доработан объект камеры, упразднен тип TAlphaColor, добавлены типы TRect и TRGBA и многое другое. Начнем по порядку.

Камера.

Самое незаметное изменение здесь - в методе 'shake' (тряска): теперь камера плавно перемещается в выбранную точку при раскачивании (вместо резкого перемещения в PE2). Также, появились новые удобные свойства - slideInfo и shakeInfo с информацией о текущем состоянии перемещения (скольжения) и раскачивания, что дает возможности, к примеру, применять размытие кадра в движении при быстром перемещении камеры:

Код:

TCameraSlide = record
  targX, targY: Single;//Положение цели
  speed: Integer;//Скорость (в процентах, от 0 до 100)
end;

TCameraShake = record
  shiftX, shiftY: Single;//Максимальное смещение
  curShiftX, curShiftY: Single;//Текущее смещение
  steps: Integer;//Общее количество раскачиваний
  curStep: Integer;//Текущий шаг раскачивания
  strength: Integer;//Сила раскачивания
  isShaking: Boolean;//Качается ли камера в данный момент?
end;

Пожалуй, это все: камера, по-прежнему, самый скромный объект движка. Вот список ее методов:

Код:

move(x, y: Single);//Моментально переместить в указанную позицию
slide(x, y: Single);//Плавно переместить в указанную позицию
shake(strength, steps: Integer);//Трясти камеру

При помощи свойства 'isActive' можно отключить камеру для последующих выводимых объектов (например, графический интерфейс). Метод 'apply' используется движком для преобразования координат всех выводимых объектов с учетом координат камеры и ее смещения при раскачивании.

Рендер.

OpenGL-рендер, используемый в движке, теперь работает намного быстрее и имеет огромное количество новых возможностей. Вместо старых glBegin/glEnd здесь используются буферные объекты (VBO), есть возможность рендера в текстуру и смены буфера вывода, присутствуют шейдеры и шейдерные эффекты (цветокоррекция, размытие, размытие в движении, резкость, ...). Вот список всех фильтров, доступных на данный момент:
  • Тонирование изображения (tone). Цветные участки изображения окрашиваются в указанный цвет.
  • Смена цвета (recolor). Красный цвет на изображении перекрашивается в указанный.
  • Цветокоррекция (correction). Коррекция цвета с учетом параметров смещения компонентов цвета в системе HSV (цветовой тон, насыщенность, яркость).
  • Заливка (fill). Полная заливка текстуры указанным цветом с сохранением прозрачных участков и указанием степени заливки.
  • Размытие (blur, motionBlur, fullBlur). Различные варианты размытия.
  • Резкость (sharp).
  • Рассеянное свечение (bloom).
  • Наложение узора (scanline). По умолчанию это эффект чересстрочной развертки (горизонтальные линии), но можно установить любое изображение, заменив его в папке с шейдерами (например, шум).
  • Искажение (displace). Искажение финального кадра в соответствии с картой искажений (например, для имитации взрывов).

В данный момент система фильтров дорабатывается для более удобного использования. Не лишним будет сказать, что теперь объект рендера наследуется от специального абстрактного класса TAbstractRender; этим решением избегается необходимость в куче callback-функций движка, назначаемых при инициализации рендера, как это было в PE2.

Движок.

Сам движок тоже претерпел значительные изменения. В функцию инициализации теперь передается объект рендера:

Код:

TPerfectEngine.init(handle, clientWidth, clientHeight, TOpenGlRender.create());

Perfect Engine, по-прежнему, может выводить как одиночные изображения, так и кадры анимации (спрайта), причем:
  • Процесс разбиения на кадры происходит при загрузке изображения, а не перед каждым выводом, как было раньше.
  • Теперь поддерживаются прямоугольные кадры (PE2 работал только с квадратными).

Что касается шрифта - он, как и прежде, может либо браться из системы, либо, загружаться из .ttf-файла в папке с программой: рендер сгенерирует в памяти спрайт с символами шрифта, который будет использоваться при выводе текста, подстраиваясь под нужные размеры с помощью технологии Mipmap. Помимо стандартных методов вывода (textOut) и подсчета ширины строки (getTextWidth) теперь появились методы для работы с форматированными строками: textOutF() и getTextWidthF():

Код:

pe.textOutF('Perfect [#ffff00ff]Engine[#]');//Здесь слово 'Engine' будет покрашено в желтый цвет

Также, движок теперь умеет считать FPS - информацию о количестве кадров в секунду можно получить, обратившись к специальному одноименному свойству. Работа с Perfect Engine, по-прежнему, проста и удобна:


Код:

const
  MAP: TArray<TArray<Byte>> = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 2, 2, 2, 3, 9, 9, 1, 2, 2],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 10, 8, 8, 8, 8, 10, 0],
    [0, 0, 0, 4, 12, 12, 12, 12, 4, 0],
    [0, 0, 0, 5, 12, 12, 12, 12, 5, 0],
    [0, 0, 0, 5, 0, 13, 13, 0, 5, 0],
    [0, 0, 0, 6, 0, 0, 0, 0, 6, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  ];

...

procedure TFrmMain.draw();
var
  i, j: Integer;
begin
  for i := 0 to high(MAP) do begin
    for j := 0 to high(MAP[i]) do
      pe.drawFrame(land, MAP[j][i], i * 64, j * 64, 64, 64);
  end;
end;

procedure TfrmMain.formCreate(sender: TObject);
begin
  TPerfectEngine.init(handle, clientWidth, clientHeight, TOpenGlRender.create());
  pe.onDraw := draw;
  land := pe.loadTexture(appPath + '/images/land.png', 64, 64);
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  TPerfectEngine.remove();
end;

При выводе любого примитива теперь поддерживается указание необязательных параметров: поворот, масштабирование и уровень прозрачности. Параметр 'isCenter' (смещение позиции объекта в его центр) был упразднен.

По ссылке ниже - тестовая программа (без исходника), демонстрирующая некоторые возможности движка.


Последний раз редактировалось SaiLight; 04.03.2019 в 18:13.
SaiLight вне форума   Ответить с цитированием
Старый 05.03.2019, 18:29   #3
SaiLight
Форумчанин
 
Аватар для SaiLight
 
Регистрация: 10.01.2009
Сообщений: 121
Репутация: 165
По умолчанию



Библиотека пользовательского интерфейса состоит из двух модулей: uiElement (реализация классов-прототипов будущих элементов интерфейса) и uiManager (менеджер интерфейса). Данная библиотека является дополнением к движку Perfect Engine 3.

uiElement

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

Код:

TUiMessage = (
  msgUpdate,
  msgDraw,
  msgParentChangePos,
  msgParentChangeWidth,
  msgParentChangeHeight,
  msgMouseMove,
  msgMouseDown,
  msgMouseUp,
  msgKeyDown,
  msgKeyUp
);

Система интерфейса задумана как 'резиновая', координаты и размеры ее элементов могут задаваться либо в пикселях, либо, в процентах. Эта возможность реализована в корневом классе TUiElement, отвечающем за расчет координат и размеров элементов. В конструктор класса передаются специальные параметры: isPrcX, isPrcY, isPrcWidth, isPrcHeight, показывающие единицы измерения, в которых задаются данные параметры элемента.

Свойства x, y, width, height предназначены для получения и установки одноименных параметров в заданных единицах измерения. Для получения пиксельных вариантов (если параметры задаются в процентах) существуют свойства pxX, pxY, pxWidth и pxHeight. Более того, для вывода элементов и взаимодействия с ними нужно иметь информацию о реальных координатах элемента на экране. Эта информация кэшируется при каждом изменении позиции и размеров в дереве элементов; получить ее можно при помощи свойств scrX и scrY.

Также, присутствуют свойства offsetX, offsetY и origin: первые два задают пиксельное отклонение от текущей позиции, а последнее - смещает точку вывода элемента следующим образом:



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

Код:

isPrcX := true
x := 100
origin := 1
offsetX := -10
offsetY := 10

Класс TUiInputElement реализует базовое взаимодействие с мышью и клавиатурой, а также, предоставляет потомкам доступ к полям FIsHovered, FIsPressed и FIsFocused. Основываясь на этих данных, можно удобно реализовать смену отображения при наведении мыши, нажатии или при получении элементом фокуса.

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

Класс TUiVisualElement является общим предком для всех визуальных элементов. Среди его свойств - isUseCamera, определяющее, использовать ли камеру движка при выводе элемента и isVisible. Невидимые элементы, как и неактивные, не обрабатывают и не распространяют сообщений по вложенным элементам.

Класс TUiTextElement реализует базовый функционал вывода текста, его свойства очень похожи на аналогичные css-свойства в веб-разработке:

Код:

padding: TUiRect;//Отступ текста от границ элемента
xPadding, yPadding: Single;//Сумма отступов по одной из осей
fontName: String;//Имя шрифта
fontSize: Integer;//Размер шрифта
fontColor: TRGBA;//Цвет шрифта
textAlign: Byte;//Выравнивание текста
lineHeight: Single;//Междустрочный интервал
autoHeight: Boolean;//Используется ли автовычисление высоты
formatted: Boolean;//Используется ли форматированный текст

При всяком изменении текста, а также, размеров элемента или отступов (padding) вызывается метод cacheRecalc, кэширующий текст в специальной структуре для более оптимизированного вывода. Этот метод разбивает текст на строки в зависимости от ширины элемента и отступов от его краев.

И, наконец, класс TUiScene наследуется от TUiInputElement и реализует сцену - корневой элемент дерева.

uiManager

Данный модуль является оберткой над uiElement и реализует работу со сценами, а также, загрузку интерфейса из json-файла и его стилизацию при помощи файла стилей. Вот набор файлов, с которыми работает менеджер:
  • markup.json - файл с разметкой и базовыми стилями
  • styles.css - файл со стилями
  • const.ini - файл с текстовыми константами

Файл с разметкой содержит в себе дерево объектов, представленное в формате json, где каждый объект имеет следующие поля:
  • class - класс элемента для автоматического создания через rtti
  • style - стиль элемента из таблицы стилей
  • scene - имя сцены-родителя, только для корневых элементов
  • isPrcX, isPrcY, isPrcWidth, isPrcHeight - описано выше, необязательные параметры
  • params - объект с перечислением свойств элемента и их значений
  • elements - объект с перечислением вложенных элементов такой же структуры

Файл стилей имеет следующую структуру:

Код:

.имя стиля
  свойство = функция(значение)
  свойство = значение
  ...

При стилизации параметры, указанные в разделе 'params' json-файла, перезаписывают одноименные параметры из таблицы стилей, если таковые имеются. Сам процесс стилизации реализован за счет методов встроенной библиотеки rtti (автоматически), благодаря чему, при появлении новых свойств в дочерних классах не требуется доработки функции записи. Свойства могут быть записаны как напрямую, так и с использованием специальной функции. На данный момент доступны следующие специальные функции:
  • rgba(r, g, b, a) - устанавливает цвет из четырехкомпонентного параметра
  • rect(left, right, top, bottom) - устанавливает свойство типа TUiRect
  • img(path) - вызывает функцию движка для загрузки изображения и записывает в свойство полученный индекс текстуры
  • font(name) - вызывает функцию движка для загрузки шрифта и записывает в свойство его имя
  • const(name) - загружает текстовую константу по имени

Вот пример работы функции:

Код:

procedure TUiStyles.setRgba(obj: TUiElement; prop: TRttiProperty; params: String);
var
  rgba: TRGBA;
  value: TValue;
  arr: TArray<String>;
begin
  arr := params.explode(',');
  rgba := TRGBA.make(
    arr[0].float(),
    arr[1].float(),
    arr[2].float(),
    arr[3].float()
  );

  TValue.make(@rgba, typeInfo(TRGBA), value);
  prop.setValue(obj, value);
end;

Также, менеджер имеет следующие публичные методы:
  • getElement(sceneName, elementName) - получение элемента
  • getConst(name) - получение текстовой константы
  • sendMessage(...) - отправка сообщения текущей и глобальной сценам
  • load(constFile, stylesFile, markupFile) - загрузка интерфейса из файлов
  • selectScene(name) - выбор сцены (создание новой при отсутствии)

Создание сцен происходит автоматически при парсинге разметки. Помимо общего набора сцен, в менеджере присутствует глобальная сцена (main), элементы которой видны всегда. В игре такая сцена может содержать, например, окно консоли, которое может быть вызвано в любой момент (как в самой игре, так и в меню). При работе со сценами, пользователю доступны специальные события: onSceneShow и onSceneHide, где могут выполняться загрузка и освобождение игровых ресурсов, а также, другие необходимые действия.

[Продолжение ниже]

Последний раз редактировалось SaiLight; 05.03.2019 в 18:40.
SaiLight вне форума   Ответить с цитированием
Старый 05.03.2019, 18:30   #4
SaiLight
Форумчанин
 
Аватар для SaiLight
 
Регистрация: 10.01.2009
Сообщений: 121
Репутация: 165
По умолчанию

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

Планы на будущее

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

В представленной ниже тестовой программе на примере класса TUiButton, унаследованного от TUiTextElement реализованы основные функции библиотеки, вот их примерный список:
  • Автоопределение высоты текстового элемента
  • Определение позиции и размеров в пикселях и процентах
  • Свойства origin и offset (элемент 'приклеен' к правому краю родителя с отступом)
  • Форматированный текст
  • Использование специальных функций (например, загрузка изображения)
  • Автопереключение сцен
  • Глобальная сцена (элемент виден на всех остальных сценах)


SaiLight вне форума   Ответить с цитированием
Старый 08.03.2019, 22:01   #5
SaiLight
Форумчанин
 
Аватар для SaiLight
 
Регистрация: 10.01.2009
Сообщений: 121
Репутация: 165
По умолчанию

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

Общие сведения

ECS - Entity-Component-System - шаблон проектирования, который позволяет разделить всю игровую логику на три части: Сущность, Компонент и Система. При проектировании с помощью ECS-подхода в игре перестают существовать объекты в нашем привычном понимании: боевые единицы, здания, декорации, а вместе с тем, уходит на второй план и привычное наследование, дерево классов. Все это заменяется набором сущностей и компонентов, которые обрабатываются системами.

Компонент - это набор данных без возможности управления ими. Для того, чтобы вычленить из общего списка компонентов разных классов определенные 'объекты', используются сущности: компоненты с одним ID сущности относятся к одному 'объекту'. Системы, в свою очередь, занимаются обработкой всех игровых процессов и, по необходимости, имеют доступ к списку компонентов для работы с ними.

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

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

Итак, наша реализация.

В своей реализации мы разбили всю библиотеку на 5 модулей:
  • ecsEntity
  • ecsComponent
  • ecsSystem
  • ecsEvent
  • ecsManager

Сущность

В модуле ecsEntity описан класс-прототип всех игровых сущностей TEcsEntity, у которого всего одно свойство - id и один метод - конструктор. Все классы игровых сущностей будут наследоваться от этого класса и в собственном уникальном методе конструктора создавать весь необходимый набор компонентов. Это сделано для того, чтобы собрать код создания компонентов для разного типа объектов в модулях с описанием этих типов. Вот, к примеру, код конструктора для сущности 'figureEntity' (прототип боевой единицы в нашей игре):

Код:

constructor TFigureEntity.create(x, y: Single; color: Cardinal; control: Boolean = false);
var
  transformComponent: TTransformComponent;
  renderComponent: TRenderComponent;
  damageComponent: TDamageComponent;
  moveComponent: TMoveComponent;
  physicComponent: TPhysicComponent;
  controlComponent: TControlComponent;
begin
  transformComponent := TTransformComponent.create(ecs.curEntity);
  transformComponent.x := x;
  transformComponent.y := y;
  transformComponent.width := 50;
  transformComponent.height := 50;
  ecs.addComponent(transformComponent);

  renderComponent := TRenderComponent.create(ecs.curEntity);
  renderComponent.color := color;
  ecs.addComponent(renderComponent);

  damageComponent := TDamageComponent.create(ecs.curEntity);
  ecs.addComponent(damageComponent);

  moveComponent := TMoveComponent.create(ecs.curEntity);
  moveComponent.speed := 5;
  ecs.addComponent(moveComponent);

  ...

  if (control) then begin
    controlComponent := TControlComponent.create(ecs.curEntity);
    ecs.addComponent(controlComponent);
  end;
end;

Мы видим, что в конструктор TFigureEntity передается набор параметров, уникальный для этого типа объектов. Причем, есть статичные параметры, задающиеся прямо в коде, а есть динамические - передающиеся в конструктор извне.

Также, в модуле ecsEntity описан менеджер сущностей, занимающийся хранением и обработкой списка сущностей: добавление, удаление и т.д.

Компонент

В модуле ecsComponent, также, описаны базовый класс компонента и менеджер компонентов. Базовый класс TEcsComponent содержит только одно свойство 'entity' - id сущности, к которой привязан данный компонент. Менеджер представляет собой особый интерес: помимо прочих, он имеет методы получения компонента по типу и ID сущности и списка всех компонентов определенного типа (для обхода системой):

Код:

function getComponent(cmpType: String; entity: Integer): TEcsComponent;
function getComponents(cmpType: String): TDictionary<Integer, TEcsComponent>;

Сам список компонентов представлен в виде сложной структуры, основанной на стандартном классе TDictionary (хэш-таблица):

Код:

TComponentsList = TDictionary<String, TDictionary<Integer, TEcsComponent>>;

Таблица в таблице. Здесь ключ в первой таблице - имя типа компонентов (например, TRenderComponent), а значение - список компонентов этого типа, где, в свою очередь, ключами выступают ID сущностей, к которым они привязаны.

Системы и события

Как и в предыдущих двух модулях, в ecsSystem описаны классы системы и менеджера систем. Причем, первый из них имеет только виртуальную процедуру update(), но он, также, является наследником класса TEcsListener. Что это за класс?

Его можно найти в модуле ecsEvent, который содержит всего три класса: TEcsListener, TEcsEvent и TEcsEventManager. Любой наследник класса TEcsListener может быть 'слушателем' события - таким образом, события рассылаются менеджером всем слушателям, что подразумевает возможность наличия нескольких слушателей для одного события.

Метод addListener(eventType, listener) добавляет слушателя в список для конкретного типа события (обычно вызывается при старте программы). Каждый раз при возникновении нового события (например gameStartEvent - начало игры) вызывается метод addEvent(event), куда передается объект - наследник TEcsEvent со своим набором параметров (уникальным для каждого типа события).

В обработчике update() менеджер обходит список событий, получает для каждого из них список слушателей и отсылает событие им, после чего список событий очищается. Для приема события на стороне слушателя в классе TEcsListener реализован виртуальный метод callEvent(event), который и вызывается менеджером.

Общий менеджер

Для упрощения работы с системой реализован класс общего менеджера TEcsManager со статичным методом инициализации, создающим глобальный объект 'ecs', к которому можно обратиться из любого модуля библиотеки. Этот класс является оберткой над остальными модулями: хранит в себе объекты вышеописанных менеджеров и реализует удобное обращение к ним посредством специальных методов.

Вот, пожалуй, и все. Наверняка, в этой реализации найдется достаточно подводных камней, так как это наш первый опыт написания подобной системы, и мы пока не опробовали ее на практике. Если такое случится - будем делиться информацией о возникших проблемах и о способах их решения в этой теме. Примера здесь не будет, так как пример к данному сообщению - и есть сама мини-игра - прототип Galaxy Boom mini, проект, собранный из модулей, описанных в этом и предыдущих сообщениях. Обо всех новостях я постараюсь сообщать в этой теме. Если кому-нибудь она покажется полезной или возникнут вопросы по реализации отдельных элементов программы - буду рад пообщаться.

Последний раз редактировалось SaiLight; 09.03.2019 в 10:33.
SaiLight вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не разрешается отладка USB (Samsung Galaxy S4) Danila7 Java Мобильная разработка (Android) 1 18.09.2016 18:05
[Аркада] Galaxy Boom mini, Perfect Light SaiLight Gamedev - cоздание игр: Unity, OpenGL, DirectX 5 14.03.2016 21:19
проблемы с samsung galaxy ace II GT-I8160 (Android 4.1.2) Андрей201421 Мобильные ОС (Android, iOS, Windows Phone) 1 15.08.2014 20:06
Региональная блокировка Samsung galaxy SIII starsv Мобильные ОС (Android, iOS, Windows Phone) 4 24.02.2014 17:21
Galaxy Boom SaiLight Gamedev - cоздание игр: Unity, OpenGL, DirectX 17 24.12.2012 14:56


23:08.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru