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

Эффекты и Анимация

Опубликованно: 01.09.2017, 13:38
Последняя редакция, Andry: 19.09.2017 17:00
  • Эффекты и Анимация
    • Анимация
    • Tween Объекты
      • SpatialTweens
      • Tweens
      • PanelTweens
      • В будщем
    • Эффекты
      • Каналы
      • Стили
      • EffectControl
    • Примеры
      • Включено Отключено Анимация на основе Tween
      • Тот же пример со Сглаживанием
      • Эффект Открытия-Закрытия

Начиная с версии 1.6, Lemur включает в себя встроенную систему анимации и фреймворк эффектов для элементов GUI, которые могут использовать для добавления эффектов к элементам GUI либо напрямую, либо путем стилей. Базовая система Анимации позволяет использовать любой тип повторяющихся со временем задач. Которые, в свою очередь, могут использовать в качестве вызова наборы Tween объектов, которые выполняют интерполяцию с течением времени. Затем система эффектов задействует в эти слои, чтобы обеспечить анимацию на основе событий соответствующую этому GUI-элементу. (Например, щелчок на кнопке может запускать анимацию «click», которая создает соответствующую задачу анимации, чтобы выдавливать кнопку, моргнуть цветом и.т.п.).

Lemur_Animation

На приведенной выше диаграмме показано разделение между различными слоями системы анимации. Внизу у вас есть Tweens, которые являются многоразовыми фрагментом, которые на самом деле и работают, могут быть сцеплены вместе или запускаться параллельны. Обычно они выполняются TweenAnimations в AnimationState. AnimationState может также выполнять любые произвольные пользовательские анимации, которые зарегистрированы в приложении. Наконец, объекты Effect в EffectControl из Spatial могут выполнять определенные анимации по требованию, и обычно это TweenAnimations (хотя они и не обязательны).

Анимация

Ядро анимации просто делает что-то в течение определенного периода времени. Lemur предоставляет состояние приложения AnimationState, чтобы обеспечить эту возможность. Отдельные объекты Animation могут быть добавлены в AnimationState, и все они будут вызываться один раз в кадре, пока конкретная анимация не сообщит, что она завершена.

Для реализации пользовательской анимации необходимо реализовать только методы animate() и cancel().

Пример:

public class MyCustomAnimation implements Animation {
    public boolean animate( double tpf ) {
        // выполнить некоторую задачу анимации
        return true; // продолжать
    }
    public void cancel() {
    }
}

Встроенная реализация анимации под названием TweenAnimation предназначена для автоматического вызова объектов Tween. Tween — это своего рода единицы интерполяции. Один Tween может перемещать Spatial из одного места в другое или поворачивать его с одного угла на другой или на оба. Объект TweenAnimation отслеживает время с момента его запуска и передает это время делегированному Tween до тех пор, пока не пройдет полная продолжительность.

TweenAnimation также поддерживает цикл, запросы о времени, оставшемся/истекшем, а также возможность быстрой перемотки задачи.

TweenAnimation:

  • isLooping(): true, если анимация зацикливается.
  • IsRunning(): true, если анимация в данный момент запущена и ещё не завершена.
  • GetLength(): возвращает настроенную длительность этой анимации.
  • GetTime(): возвращает количество времени, в течение которого анимация была запущена.
  • GetRemaining(): возвращает оставшееся время для запуска. Если анимация зацикливается, это возвращает время, оставшееся в этой итерации цикла.
  • getRemainingPercent(): возвращает оставшееся время в масштабе между 0 и 1.0 на основе полной длины анимации.
  • fastForward(): быстрая прокрутка анимации в определенное время.
  • fastForwardPercent(): быстрый прокрутка анимации в определенное время относительное значения всей её длины в промежутке 0 и 1.

См. также: javadoc

Объекты Tween

Объекты Tween представляют собой небольшие анимационные модули, которые составляют ядро многоразовой анимационной системы Lemur. Отдельные Tween объекты выполняют простые операции интерполяции на основе ввода, а затем могут быть составлены в последовательные или параллельные tween для создания более сложных анимаций.

Tween делает одну вещь. Он интерполирует данные с некоторым значением «время» между 0 и имеемой длиной. Например, Tween, который перемещает spatial объект от (0, 0, 0) до (100, 0, 0) в течение периода 5.0, будет интерполировать местоположение и применять его к spatial на основе введённого значения времени от 0 до 5,0.

myMoveTween.interpolate(1); // поместить spatial на 10, 0, 0
myMoveTween.interpolate(2.5); // поместить spatial на 50, 0, 0
myMoveTween.interpolate(5); // поместить spatial на 100, 0, 0
/// и он скрепляется так
myMoveTween.interpolate(6); // также поместить spatial на 100, 0, 0

Lemur включает в себя кучу встроенных реализаций Tween в наборах статических заводских методов.

SpatialTweens

Класс SpatialTweens javadoc предоставляет множество заводских методов управления spatial через интерполяцию.

Заводские методы:

  • move: создает Tween, который перемещает spatial из одного места в другое.
  • rotate: создает Tween, который вращает spatial от одной ориентации к другой.
  • scale: создает Tween, который масштабирует spatial из одного масштаба в другую.
  • detach: создает текущий Tween, который отделяет spatial в момент времени >= 0.
  • attach: создает текущий Tween, который прикрепляет spatial заданный родительским элементом в момент времени >= 0.

См. также: javadoc

Каждое из них может использовать текущее значение Spatial в качестве начальной или конечной точки во время создания Tween.

Заводские дополнения будут добавлены в будущем для следующего сплайна и.т.п.

Само по себе это всего лишь маленькая часть. Реальная сила заключается в том, как их можно создавать и манипулировать с помощью стандартного базового Tween.

Tweens

Это реальный класс, и проявляющий реальную силу. Набор заводских методов Tweens предоставляет встроенный набор реализаций Tween для компоновки или масштабирования/фильтрации других tween объектов. Например, последовательность tween может быть объединена для запуска по одному за раз.

Еще одна особенность — возможность сгладить шаг или применить фильтр кривой к другому Tween. Например, перемещение Tween будет линейно интерполировать из одного местоположения в другое. Часто было бы лучше выполнить более плавную интерполяцию, когда объект начинает медленно двигаться, ускоряется, а затем замедляется на другом конце. Класс Tweens включает в себя как оболочку smoothStep(), так и оболочку sineStep(), которая фильтрует «время» через кривую перед отправкой на делегированному Tween. Красота этого подхода заключается в том, что кривая может быть предоставлена ​​всему составному Tween, который может включать в себя перемещение, поворот, масштабирование, затухание и.т.п. все сразу, последовательно или параллельно. Будучи способным сгладить шаг, все это очень мощно для того, чтобы сделать анимацию немного «более сочной».

Заводские методы:

  • sequence(): создает Tween, который содержит набор делегированных tweens, которые будут запускаться последовательно.
  • parallel(): создает Tween, который содержит набор делегированных tweens, которые будут выполняться параллельно, пока не закончится выполнятся все.
  • delay(): создает no-op Tween, который ничего не делает до тех пор, пока указанное время не пройдет. Полезно в последовательности.
  • stretch(): создает Tween, который изменяет длину другой анимации, уменьшая или затягивает. (В основном масштабирует значение времени.)
  • sineStep(): создает Tween, который фильтрует время через синусоидальную функцию, чтобы сгладить интерполяцию делегированного Tween.
  • smoothStep(): создает Tween, который фильтрует время через функция Эрмита, чтобы сгладить интерполяцию делегированного Tween. Это похоже на функцию GLSL smoothstep().
  • callMethod(): создает текущий Tween, который использует рефлексию для вызова метода когда временя >= 0.
  • callTweenMethod(): создает Tween, который будет передавать время указанному методу с использованием рефлексию.

См. также: javadoc

PanelTweens

Этот класс предоставляет некоторые стандартные tweens для управления элементами GUI Лемура на основе панелей. В настоящее время существует только метод fade(), который поддерживает изменение альфа-значения Panel с течением времени.

См. Также: javadoc

В будущем

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

Эффекты

На уровне GUI элемента эффекты — это возможность связать некоторые предопределенные анимации с названиями. Некоторые GUI элементы, такие как Button(Кнопка), будут иметь встроенный набор событий, которые запускают эффекты (нажмите, отпустите, нажмите, активируйте, и деактивируйте). Вызывающий может регистрировать объекты Effect для этих названий, которые будут использоваться для создания Анимации при выполнении эффекта. В этом смысле эффект подобен многоразовой фабрике анимации.

Каналы

Часто элемент GUI будет иметь противоположные эффекты (например, открывать/закрывать, активировать/деактивировать), которые должны прерывать друг друга. Например, если анимации открытия окна выполнилась на половину, то анимация закрытия должна либо дождаться, пока она закончится, либо заменит ее. Чтобы облегчить это, эффект может предоставлять название канала. Это название канала используется для замены любого существующего эффекта, выполняемого на канале во время вызова нового эффекта.

Замененные эффекты автоматически отменяется, и новый эффект «перематывается вперед» пропорционально времени того же эффэекта. Например, если эффект открытия окна масштабирует и перемещает окно в течение 2-секундного периода, и он только на полпути, а затем его заменяет эффект закрытия. Это приведет к отмене открытия в середине операции. Затем эффект закрытия будет быстро перенаправлен на половину его собственной временной шкалы (с выполнением всех промежуточных событий). Таким образом, даже если анимация открытия занимает 2 секунды, то анимация закрытия займет всего 1 секунду, пропорциональная перемотка вперед гарантирует, что замена будет гладкой (предполагая, что два эффекта действительно противоположные).

Стили

Эффекты можно настроить с помощью атрибутов стиля, так же как и любой другой атрибут настраиваемый стилем. Отличие только в том, что значение эффектов представляет собой Карту имен для объектов Effect. API стилей автоматически объединит эти карты интеллектуальным способом на основе конфигурации содержащейся в стиле.

Например, если общий эффект кнопки зарегистрирован как (в виде языка стиля):

selector("button", "myStyle") {
    effects = [
        click:new PlayBeepEffect(),
        activate:new MyHighlightEffect(),
        deactivate:new MyUnhighlightEffect()
    ]
}

Это регистрирует набор эффектов, которые будут применяться ко всем кнопкам по умолчанию.

Затем можно это переопределить только для кнопок ползунка(slider) обычным для стиля способом:

selector("slider", "button", "myStyle") {
    effects = [
        click:new PlayClickEffect(),
        activate:null,
        deactivate:null
    ]
}

В этом случае по умолчанию Ползунки(Sliders) будут иметь только новый эффект клика и ни один из эффектов кнопки заданный по умолчанию.

Это справедливо даже при непосредственном рассмотрении класса Styles и захвате атрибутов для селекторов. Нужно просто позаботиться о создании значения карты и/или добавить настройки для любых существующих значений Карты для этого селектора.

EffectControl

Все GUI элементы Lemur, основанные на Панели(Panel), автоматически получат поддержку для запуска эффектов. Это делается путём внутреннего вызова EffectControl. EffectControl это независимый модуль, который может использоваться для любого JME Spatial. Обычным пользователям Lemur не нужно беспокоиться об этом control, поскольку полный доступ к эффектам предоставляется через базовый класс Panel.

Примеры

Без слишком сильных мудрёностей, вот несколько кратких примеров, чтобы понять, как эти части работают вместе.

Включено Отключено Анимация на основе Tween

AnimationState anim = getState(AnimationState.class);
Node someSpatial...

Tween move1 = SpatialTweens.move(someSpatial, Vector3f.ZERO, new Vector3f(100, 100, 0), 2);
Tween move2 = SpatialTweens.move(someSpatial, new Vector3f(100, 100, 0), new Vector3f(200, 0, 0), 2);
Tween rotate = SpatialTweens.rotate(someSpatial, null, new Quaternion().fromAngles(0, 0, FastMath.HALF_PI, 2);
Tween unrotate = SpatialTweens.rotate(someSpatial, new Quaternion().fromAngles(0, 0, FastMath.HALF_PI, null, 1);

// Теперь все вместе
Tween overall = Tweens.sequence(move1, rotate, Tweens.parallel(move2, unrotate));
anim.add(overall);

Вышеприведенный пример будет перемещать spatial от (0, 0, 0) до (100, 100, 0) в течение 2-секундного периода. Затем он остановится и повернется на 90 градусов в течение 2 секунд. После этого он одновременно повернется на 90 градусов и переместится в новое место. Обратное вращение продолжается только на половине конечного пути, поскольку его длина установлена на 1 секунду.

Тот же пример со Сглаживанием

// Все те же вещи сверху ... но теперь с сглаживанием движения здесь:
Tween overall = Tweens.sequence(Tweens.smoothStep(move1), rotate, Tweens.parallel(Tweens.smoothStep(move2), unrotate));
anim.add(overall);

Это, по сути, тот же пример, за исключением того, что spatial будет двигаться гораздо плавней, замедляя запуск после чего немного ускоряясь, прежде чем снова замедляться в конце. Общее время останется прежним.

Эффект Открытия-Закрытия

В этом примере мы будем настраивать эффекты открытия и закрытия и применять их к Панели(Panel). Это пример противоположных эффектов, которые прерывают друг друга.

Effect<Panel> open = new AbstractEffect<>("open/close") {
    public Animation create( Panel target, EffectInfo existing ) {
        Tween move = SpatialTweens.move(target, Vector3f.ZERO, new Vector3f(200, 200, 0), 2);
        Tween scale = SpatialTweens.scale(target, 0, 1, 2);
        return new TweenAnimation(Tweens.smoothStep(Tweens.parallel(move, scale)));
    }
}

Effect<Panel> close = new AbstractEffect<>("open/close") {
    public Animation create( Panel target, EffectInfo existing ) {
        Tween move = SpatialTweens.move(target, new Vector3f(200, 200, 0), Vector3f.ZERO, 1);
        Tween scale = SpatialTweens.scale(target, 1, 0, 1);
        return new TweenAnimation(Tweens.smoothStep(Tweens.parallel(move, scale)));
    }
}

// Теперь, когда мы создали эффекты, мы можем установить их в нашу Panel.
myPanel.addEffect("open", open);
myPanel.addEffect("close", close);

Это настраивает панель для поддержки runEffect(«open») и runEffect(«close») (предполагая, что она уже привязана к чему-то). Открытие займет 2 секунды, а закрытие займет 1 секунду.

Но ждать! Разве мы не должны что-то делать, чтобы справиться с прерыванием и прочим??? Нет. В этом случае для простых анимаций, основанных на аtween анимации, будет сделано правильное.

Если myPanel.runEffect(«close») произойдет до того, как открытие завершится, анимация открытия будет отменена, а анимация закрытия будет быстро прокручена, чтобы проиграть всё за то время, что оставалось проиграть анимации открытия.

Таким образом, если открытию оставалась только 1 секунду анимации, когда вызывается runEffect(«close»), то противоположная анимация будет быстро прокручена ​​на 0,5 секунды (половина ее времени, так как половина открытия завершена).

Самое замечательное в том, что то же самое происходит и в обратном направлении. Если закрытие частично запущено и начнет выполнятся runEffect(«open»), то открытие будет пропущено вперед так же. Целостность поддерживается.

Этот тип прерывания работает только потому, что эффектам задали каналы (в данном случае «open/close»). Эффекты, которым не задали каналы, будут работать независимо.

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

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

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