Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество

Пользовательские Control

Опубликованно: 05.05.2017, 22:49
Последняя редакция, Andry: 12.08.2017 16:44

com.jme3.scene.control.Control — это настраиваемый интерфейс jME3, который позволяет вам управлять поведением игровых объектов типа Spatials, такое как, искусственный разум NPC, ловушки, автоматические сигнализации на дверях, животных, автопилот автомобиля или платформы, все что движется и взаимодействует. Несколько экземпляров Control совместно реализуют поведение Spatial.

Чтобы контролировать глобальное поведение игры, см. «Application States » — вы часто используете AppStates и Control вместе.

Чтобы управлять поведением Spatial объектов:

  1. Создайте один элемент управления для каждого типа поведения. При добавлении нескольких элементов на один Spatial, они будут выполнены в порядке добавления.
    Например, один NPC может управляться экземпляром PhysicsControl и экземпляром AIControl.
  2. Задайте пользовательский Control и реализуйте его поведение в методе обновления Control:
    • Вы можете передавать аргументы в свой пользовательский Control.
    • Классу Control, Spatial объект предоставляет доступ к пространству и подпакетам, объекта которым привязан Control.
    • Здесь вы осуществляете «пространственные преобразования (перемещение, масштабирование, поворот), анимацию воспроизведения, проверяете его окружение, определяете, как оно действует и реагирует.
  3. Добавьте экземпляр Control в Spatial, чтобы придать ему такое поведение. Состояние игры в Spatial теперь обновляется автоматически.
  4. spatial.addControl(myControl);

Чтобы реализовать логику игры для типа Spatial, вы либо расширите AbstractControl (самый распространенный случай), либо реализуете интерфейс Control, как объясняется в этой статье.

Применение

Используйте Control для реализации поведения разных типов игровых объектов.

  • Используйте Control, чтобы добавить тип поведения (то есть методы и поля) к отдельным Spatial объектам.
  • Каждый Control имеет свой собственный цикл update(), который перехватывается в simpleUpdate(). Используйте цикл update() конкретного Control для перемещения туда соответствующих блоков кода из цикла simpleUpdate().
  • На один Spatial могут влиять несколько Control. (Очень мощный и модульный!)
  • Каждому Spatial нужен свой экземпляр Control.
  • У Control есть только доступ и контроль лишь над Spatial, к которому он присоединен.
  • Control могут быть сохранены в формате .j3o вместе со Spatial.

Примеры: вы можете написать так

  • WalkerNavControl, SwimmerNavControl, FlyerNavControl …, который определяет, как тип NPC находит свой путь в окружающем мире. Все NPC могут ходить, некоторые могут летать, другие могут плавать, а некоторые могут все это и.т.д.
  • PlayerNavControl, управляемый настроеной пользователем клавиатурой и мышью.
  • Общий контроль анимацией, который выступает в качестве общего интерфейса, который запускает анимацию (ходить, стоять, атаковать, защищать) для различных объектов.
  • A DefensiveBehaviourControl, который дистанционно управляет поведением NPC в боевых ситуациях.
  • IdleBehaviourControl, который дистанционно управляет поведением NPC в нейтральных ситуациях.
  • DestructionControl, который автоматически заменяет структуру соответствующим куском обломков после столкновения с снарядом…

Возможности безграничны. :) :)

Примеры кода

Другие примеры включают встроенный RigidBodyControl интеграции физике в JME, встроенный TerrainLODControl, который обновляет уровень детализации ландшафта в зависимости от перспективы просмотра и.т.д.

Существующие примеры в базе кода включают:

  • AnimControl.java позволяет манипулировать скелетной анимацией, включая смешивание и несколько каналов.
  • CameraControl.java позволяет синхронизировать положение камеры с положением заданной области пространства.
  • BillboardControl.java отображает плоское изображение ортогонально, например. Речевого пузыря или информационного диалога.
  • Подклассы PhysicsControl (такие как CharacterControl, RigidBodyControl, VehicleControl) позволяют добавлять физические свойства к любому Spatial. PhysicsControls связывает возможности, предоставляемые BulletAppState.

Класс AbstractControl

Самый общий способ создания элемента управления — создать класс, который расширяет AbstractControl.

AbstractControl можно найти в разделе com.jme3.scene.control.AbstractControl. Это абстрактный класс по умолчанию, который реализует интерфейс Control.

  • У вас есть доступ к булевому isEnabled()
  • У вас есть доступ к объекту Spatial пространства.
  • Вы переопределяете метод controlUpdate() для реализации поведения Spatial.
  • У вас есть доступ к методу setEnabled (логический). Это временно активирует или деактивирует поведение этого элемента управления в этой области. Когда AbstractControl отключается, цикл controlUpdate() больше не выполняется.
    Например, вы отключите IdleBehaviourControl, когда включите DefensiveBehaviourControl в Spatial.

Использование: Ваш собственный подкласс реализует три метода controlUpdate(), controlRender(), setSpatial() и cloneForSpatial(), как показано ниже:

public class MyControl extends AbstractControl implements Savable, Cloneable {
  private int index; // могут иметь настраиваемые поля -- пример

  public MyControl(){} // пустой конструктор сериализации

  /** Необязательный настраиваемый конструктор с аргументами, которые могут инициализировать настраиваемые поля.
    * Примечание: вы еще не можете изменить Spatial! */
  public MyControl(int i){
    // index=i; // example
  }

  /** Этот метод вызывается, когда элемент управления добавляется в Spatial,
    * а когда Control удаляется из Spatial (установка нулевого значения).
    * Он может использоваться как для инициализации, так и для очистки. */
  @Override
  public void setSpatial(Spatial spatial) {
    super.setSpatial(spatial);
    /* Пример:
    if (spatial != null){
        // инициализация
    }else{
        // очищение
    }
    */
  }


  /** Реализуйте свое пространственное поведение здесь.
    * Отсюда вы можете изменить граф сцены и Spatial
    * (Преобразовать их, получить и установить userdata и.т.д.).
    * Этот цикл управляет пространством, в то время как Control включен. */
  @Override
  protected void controlUpdate(float tpf){
    if(spatial != null) {
      // spatial.rotate(tpf,tpf,tpf); // пример поведения
    }
  }

  @Override
  public Control cloneForSpatial(Spatial spatial){
    final MyControl control = new MyControl();
    /* Необязательно: используйте установщики для копирования пользовательских данных в клонированный Control. */
    // control.setIndex(i); // пример
    control.setSpatial(spatial);
    return control;
  }

  @Override
  protected void controlRender(RenderManager rm, ViewPort vp){
     /* Дополнительно: рендеринг (для продвинутых пользователей) */
  }

  @Override
  public void read(JmeImporter im) throws IOException {
      super.read(im);
      // im.getCapsule(this).read(...);
  }

  @Override
  public void write(JmeExporter ex) throws IOException {
      super.write(ex);
      // ex.getCapsule(this).write(...);
  }

}

Смотрите также:

  • Дополнительные сведения о write() и read() см. В разделе «Сохранение и загрузка»
  • Дополнительные сведения о setUserData() см. В разделе Spatial.

Интерфейс управления

В менее распространенном случае, когда вы хотите создать Control, который также расширяет другой класс, создайте пользовательский интерфейс, который расширяется jME3 интерфейсом Control. Ваш класс может стать аналогом Control, реализуя интерфейс Control и одновременно расширяя другой класс.

Интерфейс Control можно найти в разделе com.jme3.scene.control.Control. Он имеет следующие сигнатуры метода:

  • CloneForSpatial(Spatial): клонирует Control и присоединяет его к клону заданному Spatial.
    Реализуйте этот метод, чтобы иметь возможность save() и load() Spatial, несущие этот Control.
    AssetManager также использует этот метод, если один и тот же Spatial объект загружается дважды. В этом случае вы можете указать, какие поля вы хотите использовать повторно (например, collisionshapes).
  • SetEnabled (boolean): Переключает логическое значение, которое включает или отключает Control. Идет с accessor isEnabled() ;. Вы проверяете его в цикле update (float tpf) перед выполнением чего-либо.
  • Существуют также некоторые внутренние методы, которые вы не вызываете из пользовательского кода: setSpatial(Spatial s), update(float tpf) ;, render (RenderManager rm, ViewPort vp).

Пример использования:

  1. Создайте пользовательский интерфейс Control.
    public interface MyControlInterface extends Control {
        public void setSomething(int x); // необязательно добавлять пользовательские методы
    }
  2. Создайте настраиваемые Control, реализующие интерфейс Control.
    public class MyControl extends MyCustomClass implements MyControlInterface {
    
        protected Spatial spatial;
    
        protected boolean enabled = true;
    
        public MyControl() { } // пустой конструктор сериализации
    
        public MyControl(int x) { // пользовательский конструктор
            super(x);
        }
    
        @Override
        public void update(float tpf) {
            if (enabled && spatial != null) {
                // Напишите собственный код для управления Spatial здесь!
            }
        }
    
        @Override
        public void render(RenderManager rm, ViewPort vp) {
            // необязательно для продвинутых пользователей, например. Для отображения формы отладки
        }
    
        @Override
        public Control cloneForSpatial(Spatial spatial) {
            MyControl control = new MyControl();
            // установить пользовательские свойства
            control.setSpatial(spatial);
            control.setEnabled(isEnabled());
            // задайте еще несколько свойств...
            return control;
        }
    
        @Override
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    
        @Override
        public void setSomething(int z) {
            // Вы можете добавить собственные методы...
        }
    
        @Override
        public void write(JmeExporter ex) throws IOException {
            super.write(ex);
            OutputCapsule oc = ex.getCapsule(this);
            oc.write(enabled, "enabled", true);
            oc.write(spatial, "spatial", null);
            // написать настраиваемые переменные ...
        }
        @Override
        public void read(JmeImporter im) throws IOException {
            super.read(im);
            InputCapsule ic = im.getCapsule(this);
            enabled = ic.readBoolean("enabled", true);
            spatial = (Spatial) ic.readSavable("spatial", null);
            // читать пользовательские переменные ...
        }
    }

Рекомендации

Используйте getControl() для получения объектов Control из Spatial. Нет необходимости создавать много ссылок на объекты. Вот пример из кода MonkeyZone:

public class CharacterAnimControl implements Control {
  ...
  public void setSpatial(Spatial spatial) {
    ...
    animControl      = spatial.getControl(AnimControl.class);
    characterControl = spatial.getControl(CharacterControl.class);
    ...
  }
}

Вы можете создавать пользовательские интерфейсы Control, чтобы набор различных Control предоставлял одинаковые методы и к ним можно было получить доступ с помощью класса класса интерфейса.

public interface ManualControl extends Control {
    public void steerX(float value);
    public void steerY(float value);
    public void moveX(float value);
    public void moveY(float value);
    public void moveZ(float value);
   ...
}

Затем вы создаете пользовательский вложенный Control и реализации методов в соответствии с контекстом:

public class ManualVehicleControl   extends ManualControl {...}

и

public class ManualCharacterControl extends ManualControl {...}

Затем добавьте соответствующие Control в список Spatial объектов:

characterSpatial.addControl(new ManualCharacterControl());
...
vehicleSpatial.addControl(new ManualVehicleControl());
...
Используйте метод getControl () в Spatial, чтобы получить конкретный объект Control и активировать его поведение!

ManualControl c = mySpatial.getControl(ManualControl.class);
c.steerX(steerX);

Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.