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

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

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

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

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

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

  1. Создайте один control для каждого типа поведения. При добавлении нескольких control на один Spatial, они будут выполнены в порядке добавления.
    Например, один NPC может управляться экземпляром PhysicsControl и экземпляром AIControl.
  2. Задайте пользовательский Control и реализуйте его поведение в методе обновления Control:
    • Вы можете передавать аргументы в свой пользовательский Control.
    • Классу Control, объект spatial предоставляет доступ к spatial и под-spatial объектам к которым прикреплен Control.
    • Здесь вы изменяете «spatial» преобразуя (перемещение, масштабирование, поворот), воспроизводя анимацию, проверяете его окружение, определя, как оно действует и реагирует.
  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, управляемый настроеной пользователем клавиатурой и мышью.
  • Общий Control анимации, который выступает в качестве общего интерфейса, который запускает анимацию (ходить, стоять, атаковать, защищать) для различных объектов.
  • DefensiveBehaviourControl, который дистанционно управляет поведением NPC в боевых ситуациях.
  • IdleBehaviourControl, который дистанционно управляет поведением NPC в нейтральных ситуациях.
  • DestructionControl, который автоматически заменяет структуру соответствующим куском обломков после столкновения с снарядом…

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

Примеры кода

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

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

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

Класс AbstractControl

Самый общий способ создания Control — создать класс, который расширяет 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(...);
  }

}

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

Интерфейс Control

В менее распространенном случае, когда вы хотите создать 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. Все права сохранены.