Основы программирования объектов — различия между версиями
Root (обсуждение | вклад) м (→Задание обработчика для объекта) |
Root (обсуждение | вклад) м (→Класс Motor) |
||
Строка 129: | Строка 129: | ||
public function void enable(); // включить мотор | public function void enable(); // включить мотор | ||
public function void disable(); // выключить | public function void disable(); // выключить | ||
+ | public function bool isEnabled(); // включен ли? | ||
public function array const paramNames(); // имена параметров | public function array const paramNames(); // имена параметров | ||
public function real const getParam(const string name); // получить параметр | public function real const getParam(const string name); // получить параметр | ||
Строка 137: | Строка 138: | ||
</source> | </source> | ||
− | Для включения и выключения мотора служат функции enable() и disable(). По-умолчанию все моторы выключены. | + | Для включения и выключения мотора служат функции enable() и disable(). По-умолчанию все моторы выключены. Функция isEnabled() возвращает текущее состояние мотора. |
Функции paramNames(), getParam() и setParam() позволяют управлять параметрами мотора. Количество и смысл этих параметров зависит от конкретного типа мотора. Например, у уже рассмотренного нами в предыдущих разделах мотора linear_speed таких параметров два: speed и force. speed определяет скорость, до которой мотор разгоняет объект, а force - максимальную силу, которую мотор прикладывает к объекту. | Функции paramNames(), getParam() и setParam() позволяют управлять параметрами мотора. Количество и смысл этих параметров зависит от конкретного типа мотора. Например, у уже рассмотренного нами в предыдущих разделах мотора linear_speed таких параметров два: speed и force. speed определяет скорость, до которой мотор разгоняет объект, а force - максимальную силу, которую мотор прикладывает к объекту. |
Версия 18:55, 9 декабря 2007
Каждое уведомление, которое получает объект (а таких уведомлений бывает 5 типов - см. предыдущий раздел), он передает в свой обработчик событий (у одного объекта может быть несколько обработчиков, но использовать эту возможность не рекомендуется).
Сам обработчик может быть реализован либо в движке, либо в модуле-расширении - это просто некоторый объект, получающий события и выполняющий определенные действия на них. Но в данном разделе нас будет интересовать прикладное программирование объектов на гайд-совместимых языках.
Для того, чтобы это стало возможным, реализован обработчик gide, который все полученные события передает гайд-объекту, а также предоставляет ряд классов для работы с объектом из прикладного кода.
Содержание |
Задание обработчика для объекта
Как уже было сказано в примере в предыдущем разделе, URL обработчика задается в файле описания объекта следующим образом:
<source lang="xml"> <model bxd="http://dao.deeptown.org/bxd/model.bxd">
<externals> <event_receiver url="gide:/media/scripts/cube_small_dynamic.gbc!CubeSmallDynamic" /> </externals>
</model> </source>
Как видим, в адресе фигурирует имя DISS-файла с байткодом (расширение gbc) и имя класса, который будет обрабатывать события нашего объекта.
Все примеры далее будут написаны на языке K++.
Вот простейший код обработчика, который никак не реагирует на события, происходящие с объектом:
<source lang="kpp"> package cube_small_dynamic;
import world;
class CubeSmallDynamic extends WorldObject { } </source>
Т.е. это просто класс, унаследованный от класса WorldObject, объявленного в модуле world.
Обработка уведомлений
Все уведомления, которые приходят к объекту, по-умолчанию передаются методам нашего объекта-обработчика, имя которых строится из типа уведомления и имени события. Более подробно об этом будет рассказано в разделах, посвященных конкретным взаимодействиям; сейчас нам важно отметить одно: чтобы обработать какое-либо уведомление, все, что нужно сделать - это добавить в тело нашего класса функцию-обработчик со специальным именем. Никаких дополнительных манипуляций, как то регистрация этого обработчика где-либо, или вызов его в зависимости от каких-либо условий, делать не нужно.
Единственное, что нужно помнить всегда - все такие функции должны быть помечены как export, поскольку вызываются они напрямую, минуя IDL.
Например, когда объект создается, ему высылается уведомление о состоянии объекта "init". Для того, чтобы обработать это уведомление, нужно определить в нашем классе метод State_init без параметров:
<source lang="kpp"> class CubeSmallDynamic extends WorldObject {
export function void State_init() { // Функция будет вызвана в момент создания объекта }
} </source>
Функции и классы модуля world
Класс Object
Этот класс является прародителем всех классов, представляющих объекты виртуального пространства. В нем определены следующие методы:
<source lang="kpp"> class Object {
constructor connect(const uid UID); // создает объект по его UID public operator Object = (const Object obj); // оператор присваивания public function uid const getUID(); // возвращает UID объекта public function bool const isLocal(); // true если объект находится на текущем сервере
} </source>
Отдельного комментария заслуживает лишь метод isLocal(). Он возвращает true, если объект, с которым мы работаем, находится на том же сервере, на котором находится наш обработчик. Дело в том, что объекты в сети Диптауна могут передаваться от сервера к серверу в процессе существования, и если объект находится на другом сервере, общение с ним происходит по относительно медленному механизму событий сетевого движка.
Класс WorldObject
Этот класс унаследован от Object и представляет собой интерфейс для объекта пространства. В нем определены следующие методы:
<source lang="kpp"> class WorldObject extends Object {
constructor connect(const uid UID); // аналогично public function WorldObject const guest(); // сброс привелегий public function array const motorNames(); // список моторов public function Motor const getMotor(const string name); // мотор по имени public function Sensor const createSensor(const string url, const string signal); // создать сенсор
} </source>
Функция guest возвращает копию данного объекта, не обладающую привелегиями управления своими моторами и сенсорами. На данный момент, просто не обращайте на нее внимания.
Функция motorNames() возвращает массив строк - имен моторов, которые установлены на объекте. Напоминаю, что сами моторы перечислены в файле описания объекта и не могут быть динамически добавлены или удалены.
Функция getMotor() возвращает мотор по его имени (см. описание класса ниже).
Функция createSensor() создает сенсор. Первый параметр - это URL сенсора, который, как обычно, состоит из типа и адреса, разделенных двоеточием. Второй параметр - имя сигнала, который будет передан нашему обработчику в случае срабатвания сенсора. В классе должен быть определен метод Signal_xxx, где xxx - это имя сигнала. Например:
<source lang="kpp"> class MyObject extends WorldObject {
export function void State_init() { // Создаем сенсор: this.createSensor('type:address', 'makaka'); }
// Функция-обработчик сигнала makaka, который будет послан сенсором // в случае его срабатывания: export function Signal_makaka(const bytea args) { // Реакция на сигнал... }
} </source>
Обратите также внимание, что в функцию-обработчик сигнала передается параметр типа bytea. Его значение зависит от конкретного сенсора, здесь могут быть произвольные параметры, упакованные в бинарную строку. Для их распаковки реализована вспомогательная функция parseArguments().
Класс Scene
Пока не рассматриваем.
Класс Motor
Данный класс предоставляет интерфейс мотора. Объекты этого класса создаются путем вызова метода getMotor() объекта-обработчика.
<source lang="kpp"> class Motor {
public operator Motor = (const Motor what); public function void enable(); // включить мотор public function void disable(); // выключить public function bool isEnabled(); // включен ли? public function array const paramNames(); // имена параметров public function real const getParam(const string name); // получить параметр public function void setParam(const string name, const real value); // установить параметр public function array const statusNames(); // имена статусов public function real const getStatus(const string name); // получить статус
} </source>
Для включения и выключения мотора служат функции enable() и disable(). По-умолчанию все моторы выключены. Функция isEnabled() возвращает текущее состояние мотора.
Функции paramNames(), getParam() и setParam() позволяют управлять параметрами мотора. Количество и смысл этих параметров зависит от конкретного типа мотора. Например, у уже рассмотренного нами в предыдущих разделах мотора linear_speed таких параметров два: speed и force. speed определяет скорость, до которой мотор разгоняет объект, а force - максимальную силу, которую мотор прикладывает к объекту.
Аналогично, statusNames() и getStatus() позволяют получать статусы мотора, которые также зависят от конкретного типа мотора.
Класс Sensor
Данный класс предоставляет интерфейс сенсора. Объекты этого класса создаются путем вызова метода createSensor() объекта-обработчика. Обратите внимание, что сенсоры никак не проиндексированы в объекте, т.е. создав сенсор, невозможно потом получить его интерфейс по имени или еще каким-либо способом. Поэтому, если Вам требуется изменять какие-то параметры сенсора после его создания, сохраняйте его экземпляр в полях класса.
<source lang="kpp"> class Sensor {
public operator Sensor = (const Sensor what); public function void enable(); // включить сенсор public function void disable(); // выключить сенсор public function void erase(); // удалить сенсор public function array const paramNames(); // список параметров public function getParam(const string name); // получить параметр public function void setParam(const string name, const string value); // установить
} </source>
Функции enable() / disable() включают / выключают сенсор. В отличие от моторов, при создании сенсор по-умолчанию включен.
Функция erase() удаляет сенсор. Все обращения к другим методам после erase() приведут к генерации исключения.
Функции paramNames() / getParam() / setParam() управляют параметрами сенсора. В отличие от параметров моторов, параметры сенсоров могут иметь произвольный простой тип. Функция getParam() может вернуть:
- целое число
- массив целых чисел
- вещественное число
- массив вещественных чисел
- uid
- массив из uid
- строку.
В setParam() значение параметра нужно указывать в виде строки с точным указанием низкоуровневого типа (на уровне реализации - стандартная строка для типа vary). Например, "dword 3" - целое число 3; "float 3.1,3.2,3.3" - массив из трех вещественных чисел, и т.д.