Основы программирования объектов

Материал из Deeptown Manual
Версия от 14:01, 27 апреля 2008; Root (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Каждое уведомление, которое получает объект (а таких уведомлений бывает 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!cube_small_dynamic/CubeSmallDynamic" />
   </externals>

</model> </source>

Как видим, в адресе фигурирует имя DISS-файла с байткодом (расширение gbc) и имя класса, который будет обрабатывать события нашего объекта. Обратите внимание, что имя класса - полное; оно состоит из имени модуля (слово после package), символа "/" и имени класса.

Все примеры далее будут написаны на языке K++.

Вот простейший код обработчика, который никак не реагирует на события, происходящие с объектом:

<source lang="kpp"> package cube_small_dynamic;

import World; using World;

class CubeSmallDynamic extends WorldObject { } </source>

Т.е. это просто класс, унаследованный от класса WorldObject, объявленного в модуле World.

Обработка уведомлений

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

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

<source lang="kpp"> class CubeSmallDynamic extends WorldObject { public:

   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 { public:

   function void State_init()
   {
       // Создаем сенсор:
       this.createSensor('type:address', :makaka);
   }
   // Функция-обработчик сигнала makaka, который будет послан сенсором
   // в случае его срабатывания:
   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 bool isEnabled(); // включен ли?
   public function void erase(); // удалить сенсор
   public function array const paramNames(); // список параметров
   public function getParam(const string name); // получить параметр
   public function void setParam(const string name, const value); // установить

} </source>

Функции enable() / disable() включают / выключают сенсор. В отличие от моторов, при создании сенсор по-умолчанию включен. isEnabled() возвращает текущее состояние.

Функция erase() удаляет сенсор. Все обращения к другим методам после erase() приведут к генерации исключения.

Функции paramNames() / getParam() / setParam() управляют параметрами сенсора. В отличие от параметров моторов, параметры сенсоров могут иметь произвольный простой тип. Функция getParam() может вернуть:

  • целое число
  • массив целых чисел
  • вещественное число
  • массив вещественных чисел
  • uid
  • массив из uid
  • строку.

В setParam() значение параметра нужно указывать в том же виде, в котором его вернула getParam(). Более подробно это описано в документации по конкретным сенсорам.

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты