Документация/Статьи/Обзор редактора логики
From NeoAxis Engine Wiki
| Language: | Status: | Approved |
Contents |
Описание
Редактор логики - это составная часть редактора карт. Редактор логики предназначен для создания специфичных для карты алгоритмов, т.е. таких, которые нужны только на этой карте.
В редакторе можно создавать классы, и определять для них методы и переменные. Методы - это записанные алгоритмы. Причем записывать их можно двумя способами: Designer Type (с помощью пользовательского интерфейса) и Script Type (на языке программирования C#).
Одной из ключевых возможностей редактора, является возможность создавать классы, которые надстраиваются над определенным классом игрового объекта. Данная возможность позволяет создавать обработчики событий игровых классов. Примером использования, может служить надстройка над типом Region. У класса Region есть метод ObjectIn - событие, когда персонаж попадает внутрь области. В редакторе логики, мы можем написать такой алгоритм, что попадая в определенное место на карте, обозначенное объектом Region, впереди игрока обрушивалась балка с потолка.
Запуск редактора логики
Редактор логики запускается непосредственно из редактора карт. Чтобы запустить редактор, нужно открыть карту и затем в меню World нажать кнопку Logic Editor.
Общий вид
Окно редактора логики имеет 4 основных области:
- 1 - Верхняя панель.
- 2 - Окно со списком классов.
- 3 - Рабочее окно.
- 4 - Окно вывода.
Ознакомимся с каждым элементом подробнее.
Верхняя панель
Верхняя панель состоит из главного меню и пары кнопок для быстрого вызова функций. Опишем основные функции главного меню.
Меню File.
Save Map сохраняет изменения карты.Меню View.
Настройка вида окна редактора.Class List делает видимым окно классов.
Output делает видимым окно вывода, если соответствующее окно было закрыто.
Меню Tools.
Run Simulation запускает карту.Build Test проверяет алгоритмы на синтаксические ошибки.
Окно со списком классов
Окно служит для создания классов логики карты. Здесь вы можете добавлять классы, а к классам добавлять методы и переменные.
Добавление нового класса
Добавление нового класса к логике карты осуществляется по нажатию кнопки Create Class контекстного меню элемента Map Classes в списке Классов.
Предварительно новый класс настраивается в специальном окне.
Помимо имени класса необходимо указать его тип. Класс может быть двух типов:
- Static. Обычный класс.
- Entity. Класс, надстраиваемый над одним из классов игровых объектов. В поле Entity Class Type указывается над каким именно классом будет надстраиваться создаваемый класс.
Контекстное меню класса
Работа с классом осуществляется, в основном, через его контекстное меню. Рассмотрим функции доступные для изменения класса.
Edit (изменение). Позволяет сменить имя класса.
Delete (удаление). Позволяет удалить класс.
Create Method (создание метода). Добавляет метод к классу. Можно создать как произвольный пользовательский метод (меню Method), так и надстройку над методом базового Entity-класса. Кроме того, необходимо выбрать способ создания метода: Designer Type или Script Type.
Если добавляется пользовательский метод, то необходимо указать тип возвращаемого функцией значения. Если нет необходимости, чтобы функцию возвращала значение, то указывается тип void. Также при необходимости нужно указывать список входных параметров. Каждый параметр характеризуется именем и типом значения.
Create Variable (создание переменной). Добавляет переменную к классу. Необходимо указать название переменной и ее тип. В качестве типа могут выступать как простые типы, вроде числа или строки, так иодин классы игровых объектов.
Если выставлен флаг Serialization, то значение переменной будет сохраняться при сохранении мира (Load/Save в Game.exe).
Create Custom Script Code. Позволяет присоединять к классу произвольный код, который может содержать методы и объявления переменных. К примеру, Custom Script Code позволяет определять сложные переменные, такие как списки, которые нельзя добавить с помощью меню Create Variable.
Рабочее окно
В рабочем окне записываются алгоритмы карты. Окно имеет различный вид, в зависимости от типа метода.
Неизменно наверху окна находится панель вкладок, с помощью которой можно переключаться между окнами редактирования различных методов.
Чтобы перейти в режим редактирования класса, необходимо щелкнуть по нему левой кнопкой мыши дважды.
Designer Type
В режиме Designer Type рабочее окно состоит из двух областей: списка команд Actions и окна редактирования команды.
Designer Type подразумевает создание алгоритмов с помощью пользовательского интерфейса. Для добавления и удаления команд имеются две кнопки над списком Actions.
Также эти и другие функции редактирования доступны из контекстного меню элементов списка команд.
Рассмотрим каждую из этих функций:
- Insert (вставка). Добавляет новую команду перед текущей. Подробнее о командах в Designer Type написано ниже.
- Insert (After Current) (вставка после текущего). Добавляет новую команду после выбранной. Доступно только для операторов, подразумевающих использование нескольких команд внутри себя. Это такие операторы как if (условный оператор) и while (цикл).
- Copy (копирование). Копирует выбранную команду в буфер для последующий вставки.
- Paste (вставка). Вставляет команду из буфера перед текущей.
- Delete (удаление). Удаляет выбранную команду из списка.
Команды в Designer Type
Окно добавления команды выглядит следующим образом.
Создание команды проходит рекурсивно. В окне Choose Action выбирается какое-либо действие, для этого по нему нужно сделать двойной щелчок. Далее в том же окне добавленное действие настраивается: выбираются параметры, операторы, свойства. Для настройки вызывается то же самое окно Choose Action. Разница лишь в том, что изменяется список доступных методов - будут предложены лишь те, которые актуальны для добавленной в первом окне команды. Добавленное в новом окне, действие настраивается с помощью того же окна. Окно Choose Action появляется пока не настроена вся команда. Тогда, нажимая на кнопку Ok последовательно во всех открывшихся окнах, мы в итоге возвращаемся к самому первому окну Choose Action, нажимаем в нем Ok и команда появляется в списке.
Элементы команды, доступные для редактирования, подсвечиваются как гиперссылка.
Основные комнады
| Название | Описание |
|---|---|
| Get Entity | Получение доступа к игровому объекту. Нажав на [...], можно получить доступ к свойствам объекта. |
| This Members | Переменные-члены класса. Т.е. это те переменые, которые вы создали с помощью функции Create Variable. Кроме того сюда относится переменная Owner, которая ссылается на "хозяина" объекта. |
| Control | Операторы.
|
| Local Variables | Работа с локальными переменными. С помощью команд данного блока можно определить временную переменную (оператор declare) или использовать уже определенную. Кроме того, в этом блоке доступны параметры функции. |
| Static Members | Осуществляет доступ к статичным функциям различных классов. |
| Comment | Добавляет пользовательский комментарий, который может содержать пояснение к команде или командам, облегчающий понимание алгоритма. |
Перечисленные выше типы можно назвать главными, т.к. с них начинается запись любой команды. Теперь коснемся остальных действий, которые можно выбрать в окне Choose Action.
Команды для игрового объекта
Использование игрового объекта через GetEntity. Выбрав эту команду и указав игровой объект, далее можно его использовать различным способом.
| Название | Описание |
|---|---|
| as | Оператор преобразовывает объект в другой класс. Может использоваться, например, при преобразовании объекта класса MapObject в объект класса Character. Такое преобразование должно использоваться вкупе с проверкой, принадлежит ли объект к данному классу с помощью оператора is. |
| is | Оператор возвращает True, если объект принадлежит к заданному классу. К примеру, имеется объект общего для всех объектов карты класса MapObject, но нам требуется узнать, не является ли объект игровым персонажем. Тогда мы воспользуемся оператором is и проверим, не принадлежит ли объект к классу Character. |
Кроме того, можно использовать свойства и методы объекта. Для каждого типа объекта определены свои свойства и свои методы.
Условные выражения
Условия используются в операторах If/Then/Else, While, а также могут быть значениями переменных или параметров типа Boolean. Результатом условного выражения является либо истина (True), либо ложь (False).
В качестве условных выражений могут использоваться логические операции. Их можно найти в среди статичных функций типа Boolean. Рассмотрим перечисленные там логические операции.
| Операция | Описание |
|---|---|
| Boolean == Boolean | Сравнение. Истинно, если аргументы имеют одинаковые значения. |
| Boolean != Boolean | "Не равно". Истинно, если аргументы имеют разные значения. |
| ! Boolean | Логическое НЕ. Инвертирует значение аргумента. |
| Boolean and Boolean | Логическое И. Истинно, если истинны оба аргумента. |
| Boolean or Boolean | Логическое ИЛИ. Истинно, если истинен хотя бы один аргумент. |
Кроме того, элементами логическими выражения могут различные функции сравнения всевозможных типов. К ним относятся следующие операции.
| Операция | Описание |
|---|---|
| == | Сравнение. Истинно, если аргументы имеют одинаковые значения. |
| != | "Не равно". Истинно, если аргументы имеют разные значения. |
| < | Меньше. Истинно, если первый аргумент меньше второго. |
| > | Больше. Истинно, если первый аргумент больше второго. |
| <= | Меньше или равно. Истинно, если первый аргумент меньше или равен второму. |
| >= | Больше или равно. Истинно, если первый аргумент больше или равен второму. |
Условный оператор
Условный оператор if\then\else можно найти в списке действий в разделе Control. Общий вид условного оператора:"if условие then действие1 else действие2"
В поле условие вписываются условные выражения, речь о которых шла в разделе выше. Если условие выполняется, другими словами, условное выражение принимает значение True, то выполняются операторы из блока then (действие1). Если же условие не выполняются, то выполняются операторы из блока else (действие2).
Блок else не обязателен к заполнению. В случае, когда данный блок опущен, условный оператор принимает еще более простой вид:
"if условие then действие"
Оператор цикла
Оператор цикла расположен в свитке Control списка команд. Общий вид оператора цикла:"while условие действие"
Поле условие должно содержать условное выражение. До тех пор пока оно выполняется, циклично выполняются операторы блока while (действие). Т.е. сначала проверяется условие, если оно верно выполняются следующие за ним операторы. Затем условие опять проверяется и если оно еще верно, то выполняются операторы. И так далее до тех пор, пока условие выполняется.
Необходимо заметить, что с оператором цикла нужно быть осторожным, ведь если условие никогда не будет иметь значение False, то цикл будет бесконечным и не закончит свою работу. Такая ситуация может привести к ошибке.
Математические операции
В редакторе логике вы можете найти множество математических операций. Для таких операций как сложение, вычитание, умножение, деление имеются специальные методы-члены у различных числовых классов. К таким классам относятся:
- Int32 - целочисленный, знаковый.
- Single - дробный, знаковый.
Для более сложных операций имеется специальный класс Math. Приведем описание его методов.
| Название | Описание |
|---|---|
| DegToRad | Функция, переводящая градусы в радианы. |
| RadToDeg | Функция, переводящая радианы в градусы. |
| Sqrt | Функция квадратного корня. |
| Sin | Функция синуса угла, заданного в радианах. |
| Cos | Функция косинуса угла, заданного в радианах. |
| Tan | Функция тангенса угла, заданного в радианах. |
| ASin | Функция арксинуса, возвращающая угол в радианах. |
| ACos | Функция арккосинуса, возвращающая угол в радианах. |
| ATan | Функция арктангенса. Имеется два варианта этой функции.
|
| Pow | Функция возведения числа в степень, где первый аргумент - основание, а второй - степень. |
| Exp | Функция возвращает значение экспоненты (e), возведенной в степень аргумента. |
| Floor | Функция возвращает наибольшее целое число, меньшее или равное по значению числу или выражению, заданного аргументом. |
| Log | Функция логарифма. Имеется два варианта этой функции.
|
| Log10 | Функция десятичного логарифма. |
Базовые методы
В данном разделе будут приведены основные операции, которые могут вам понадобиться при создании логики карты.
Далее будут представлены статические классы и описания их членов. Все эти классы находятся в свитке Static Members списка команд.
Класс Entities.
| Название | Описание |
|---|---|
| Create | Создание игрового объекта. Имеется два варианта этой функции:
Отличаются эти функции лишь способом передачи типа объекта: с помощью класса EntityType, или с помощью строки с именем типа. Второй параметр parent должен содержать в себе владельца игрового объекта. Для объктов на базе MapObject, родителем всегда будет Map.Instance. |
| GetByName | Получение игрового объекта по имени. После этой команды можно использовать оператор as или is, о которых написано здесь. |
| GetUniqueName | Генерирует уникальное имя для игрового объекта. |
| TickDelta | Промежуток времени между тиками в секундах. Каждый тик происходит обновление всех систем движка (игровых объектов, устройств ввода). По умолчанию в секунду производится 30 тиков, т.е. TickDelta будет равен 1/30 секунды. |
Класс EnityTypes.
| Название | Описание |
|---|---|
| GetByName | Получение типа игрового объекта по имени. |
Класс Logic.
| Название | Описание |
|---|---|
| Wait | Ожидание. Выполнение, следующих за этим оператором команд, приостанавливается на указанное время. Движок, при этом, продолжает свою работу.
Пример: мигающий источник света. Мы можем включать\выключать источник света в цикле, вызывая функцию Wait в каждой итерации. При этом задержка не будет сказываться на игре: задержка не отразится на взаимодействии остальных объектов, игрок сможет управлять своим персонажем. |
Script Type
В режиме Script Type рабочее окно - это текстовый редактор с подсветкой синтаксиса, в котором пишется исходный код метода на языке C#.
Этот режим весьма удобен для программистов. Написание кода в режиме Script Type немногим отличается от написания кода проекта в среде программирования (например, в Visual Studio).
Компилирование кода осуществляется на этапе запуска карты. Кроме того, можно проверить код на ошибки, нажав кнопку Build Test.
Окно вывода
В окне вывода собираются ошибки и предупреждения, выявленные редактором после тестовой сборки логики.
Добавление логики к объектам карты
Основными элементами логики карты являются надстраиваемые классы. Чтобы добавить логику к объекту карты, необходимо указать логический класс объекта. За это отвечает параметр Logic Class.
На выбор в качестве логического класса объекта, предоставляется список классов логики карты доступных для этого объекта. Разумеется, доступны лишь те классы, которые основаны на тех же классах, что и класс самого объекта.
Урок - Designer Type
В этом уроке мы познакомимся с созданием логики карты в режиме Designer Type. Настроим логику так, чтобы при попадании главного персонаж в регион, загорался источник света, а при выходе из региона - гас.
Для теста логики нам понадобится карта состоящая из шести объектов:
- Ландшафт (HeightmapTerrain).
- Небо (SkyDome).
- Directional-источник света (Light).
- Точка старта (SpawnPoint).
- Регион (Region).
- Spot-источник света (Light).
О том, как создавать карты можно прочитать в этом уроке.
Главным образом, из всех объектов карты нас интересуют два: регион и spot-источник света. К ним и будет применена логика карты.
Начнем с того, что запустим редактор логики. Нажмите кнопку Logic Editor в меню World.
Главная наша задача - сделать надстройку над классом Region. Добавим соответствующий класс. Для этого нажмем правой кнопкой на элементе Map Classes списка Class List и в появившемся меню нажмем кнопку Create Class.
В окне создания класса укажем имя класса (например, Region_0), тип - надстраиваемый класс (Entity) и базовый класс - Region. После этого нажмем кнопку Ok.
Наш класс добавлен в список классов. Следующий шаг - добавление методов к классу. Начнем с метода, отвечающего за появление персонажа в регионе. Нажмем правой кнопкой на наш класс, выберем пункт Create Method. Среди методов выберем ObjectIn (именно он вызывается при попадании персонажа в регион). И, наконец, выберем способ создания метода: Designer Type.
Теперь заставим наш метод включать источник света. Добавим команду, нажав на кнопку Insert над списком Actions.
Чтобы получить доступ к источнику света, нам понадобится функция GetEntity. Кликните по ней дважды.
В качестве параметра у GetEntity значится null. Изменим параметр, кликнув по нему.
Нужный нам объект - spot-источник, который в нашем случае называется Light_0.
Теперь обратимся к свойству DiffuseColor нашего источника света. Для этого нужно кликнуть по надписи [...].
Дважды щелкнем по DiffuseColor в списке.
Теперь присвоим цвету источника значение. Начнем с оператора присваивания. Кликнем по [...].
И выберем оператор =, дважды кликнув по нему.
Осталось указать присваиваемое значение. Нажмем на аргумент null.
Цвет источника - это значение типа ColorValue. Чтобы создать новое значение данного типа, обратимся к списку Static Members, в котором выберем тип ColorValue. Теперь дважды щелкнем на одноименной функции (нас интересует вариант с тремя параметрами: r, g и b).
При попадании главного персонажа источник должен гореть ярко, а значит его цвет должен быть белым. Т.е. каждая компонента его цвета будет равна 1. Нажмем на первый параметр null.
Дважды кликнем по элементу Constant. Нам будет предложено значение по умолчанию, равное нулю. Нажмем на него, чтобы изменить на единицу.
Проделаем то же самое с остальными двумя компонентами цвета. После этого нажмем на кнопку Ok.
Во всех остальных окнах также нажмем Ok и увидим получившуюся команду.
С событием, связанным с попаданием главного персонажа в регион, мы закончили. Теперь нужно проделать все те же операции, но для обратного события - выхода главного персонажа из региона. Функция, вызываемая при этом событии, называется ObjectOut. Кроме того, свет мы будем тушить, а значит компоненты цвета источника будут равны нулю.
Не забудем сохранить карту вместе с ее логикой.
Теперь перейдем в окно редактора карт, чтобы добавить, созданный нами, логический класс к региону. Выделим регион на карте и укажем его параметр LogicClass.
Выберем класс Region_0 в предлагаемом списке и нажмем кнопку Ok.
Последний шаг - это небольшая мелочь, без которой не получилось бы увидеть зажигание света при попадании в регион. Необходимо выключить наш источник, т.е. сделать его цвет черным, чтобы заметить изменение цвета при срабатывании события.
Запустим карту в режиме симуляции, чтобы посмотреть, что у нас получилось.
При попадании главного персонажа в регион, свет загорается. И гаснет, когда персонаж из региона выходит. А значит логика карты работает!
Урок - Script Type
В этом уроке мы опробуем возможности скриптового режима редактора логики. Для демонстрации возможностей будем использовать ту же карту, что и в предыдущем уроке. Как и в предыдущий раз, мы будем использовать события попадания и выхода главного персонажа в регион. Но на этот раз, заставим источник света плавно менять свой цвет.
Начнем с того, что добавим класс, надстраиваемый над объектом типа регион. Нажмем правой кнопкой на элемент Map Classes и выберем пункт Create Class.
В появившемся окне укажем имя класса, тип и класс, над которым будет произведена надстройка. Назовем класс Region_0. Т.к. нас интересует надстраиваемый класс, то в качестве типа выберем Entity. А классом для надстройки выберем Region.
Для управления источником света, нам понадобится следить за тем, находится персонаж в регионе или нет. Заведем соответствующую переменную. Нажмем правой кнопкой на класс Region_0 и выберем пункт Create Variable.
Зададим тип переменной - Boolean (логический тип, имеющий два значения: True (истина) и False (ложь)). А также укажем имя переменной - characterInRegion.
Переменная создана. А значит нужно добавить контроль ее значения. При попадании персонажа в регион, вызывается событие ObjectIn. Добавим соответствующую функцию к классу Region_0. Нажмем правой кнопкой на класс и выберем меню Create Method. Затем выберем событие ObjectIn и способ записи алгоритма - Script Type.
При попадании персонажа в регион, необходимо менять значение нашей переменной characterInRegion на значение True. В рабочем окне напишем следующий код:
characterInRegion = true;
Теперь нам необходимо отследить обратное событие - выход персонажа из региона. В нем мы должны поменять значение нашей переменной на значение False, а также потушить наш источник света. Добавим функцию ObjectOut к классу Region_0 и напишем в рабочем окне следующий код.
characterInRegion = false; ((Light) Entities.Instance.GetByName( "Light_0" )).DiffuseColor = new ColorValue(0, 0, 0);
А сейчас к перейдем самому интересному! Будем каждый кадр тик менять цвет источника света. Если персонаж находится внутри региона, то заставим источник плавно менять свой цвет с зеленого на красный. Событие, вызываемое каждый тик - это метод Tick. Добавим его к нашему классу Region_0. Ниже приведен код метода.
if(characterInRegion) { float t = (((int)(EngineApp.Instance.Time * 1000)) % 3000) / 3000.0f; float r = -4 * t * t + 4 * t; float g = 4 * t * t - 4 * t + 1; ((Light) Entities.Instance.GetByName( "Light_0" )).DiffuseColor = new ColorValue(r, g, 0); }
Цвет источника меняется циклично. Число 3000 здесь - это период смены цвета в миллисекундах.
Сохраним логику карты через меню File -> Save Map.
Нам осталось лишь задать логический класс для объекта регион. Для этого перейдем в редактор карт, выделим регион и укажем ему параметр LogicClass.
В появившемся окне выберем класс Region_0 и нажмем кнопку Ok.
Запустим нашу карту в режиме симуляции.
Зайдя в область региона, увидим, что источник света начинает плавно менять свой цвет.
















































