Статьи

Создайте стильный 3D-интерфейс с Papervision3D: эффекты и подменю

Во второй и последней части этого урока мы дополним наш интерфейс трехмерного меню специальными эффектами и подменю, включая трехмерные компоненты, такие как переключатели.

Продолжение части 1: Структура


  1. Создайте стильный 3D-интерфейс с Papervision3D: структура
  2. Создайте стильный 3D-интерфейс с Papervision3D: эффекты и подменю

Вернитесь к ссылке предварительного просмотра и посмотрите на MainMenu3D в течение нескольких секунд, чтобы увидеть этот эффект в действии. Этот класс будет применять искажение ко всем DisplayObject3D внутри MainMenu3D. Его список обязанностей:

  1. создать новый пользовательский растровый рисунок для использования в качестве DisplacementMapFilter для каждого цикла таймера
  2. добавить случайный таймер, который зацикливается и применяет фильтр к назначенному массиву ViewportLayers
  3. воспроизводить звук каждый раз, когда применяется эффект
  4. обеспечить внешний доступ для активации и деактивации эффекта

Этот класс будет выполнять свою работу без необходимости добавления в список отображения. Это также не расширяет любой другой класс.

Создайте новый класс, назовите его DistortionEffect3D и сохраните его вместе с остальными классами. Вставьте код ниже в это:

Опять же, см. Комментарии рядом с каждым свойством для краткого описания.


Добавьте код ниже внутри метода конструктора:

Здесь необходимые свойства назначаются и сохраняются для справки позже, чем вызывается метод createDistortion ().


Этот метод также будет вызываться каждый раз при завершении случайного таймера. Добавьте код ниже после конструктора:

Каждый раз, когда вызывается этот метод, из объекта Shape создается новое изображение BitmapData. Затем эти BitmapData применяются к растровому изображению, которое затем используется в качестве базового изображения для эффекта искажения. В конце метода таймеру назначается другая длительность от 5 до 20 секунд, и он повторяется только один раз.


По завершении работы таймера TweenLite используется для применения эффекта, воспроизведения звука, а после завершения вызывает метод createDistortion (), чтобы начать все заново. Добавьте код ниже:

Если для свойства _active установлено значение true, фильтр применяется, а если нет, цикл просто запускается снова, пропуская эффект. Давайте добавим 2 вспомогательных метода:

Метод playSound () воспроизводит звук с соответствующей громкостью для интенсивности эффекта. $ scaleX находится в диапазоне от 50 до 100, поэтому громкость звука будет варьироваться от 0,5 до 1. Метод assignFilter () вызывается при каждом обновлении TweenLite и применяет преобразованный фильтр ко всем элементам ViewportLayers в _viewportLayerArray.


Как вы видели по ссылке предварительного просмотра, после нажатия кнопки MainMenu3D покидает сцену и заменяется либо игрой, либо подменю. Когда это произойдет, нам не понадобится эффект, пока MainMenu3D снова не вернется на сцену. Следующие два метода позаботятся об этом для нас:

И это завершает класс DistortionEffect3D.


Вернитесь к методу setMenuEffect () MainMenu3D и добавьте в него приведенный ниже код:

Не забудьте раскомментировать объявление свойства _distortion в верхней части класса. Все, что мы здесь делаем, — это просматриваем все UIComponent3D внутри MainMenu3D, чтобы получить доступ к их ViewportLayers и поместить их все в массив. После того, как собраны все слои ViewportLayers, для которых вы хотите применить эффект искажения, самое время создать экземпляр DistortionEffect3D и передать массив в качестве единственного параметра. Затем перейдите к методу prepareIntro () MainMenu3D и добавьте приведенный ниже код в самом начале:

Теперь добавьте код, чтобы отключить его, когда MainMenu3D не является текущим меню. Перейдите к методу startExit () в MainMenu3D и добавьте код в самом начале:

Идите вперед и запустите программу. Пример результата связан здесь . Вы должны увидеть и услышать, как эффект искажения повторяется где-то между 5 и 20 секундами.


А сейчас давайте сосредоточимся на добавлении еще 3 эффектов для улучшения нашего интерфейса. Во-первых, класс StaticGlow3D, который добавит прозрачное свечение для всех меню. Мы хотим, чтобы наши меню выглядели голографическими, и этот класс обеспечит этот эффект. Его обязанности:

  1. нарисовать BitmapData в качестве базового изображения для эффекта
  2. обеспечить внешний контроль для анимации входа и выхода
  3. есть 2 различных способа анимировать эффект и соответствовать тому, как открывается активное меню

Создайте новый класс с именем StaticGlow3D и расширьте для него DisplayObject3D. Вставьте код ниже, заменив все внутри, чтобы начать:

Все переменные объявлены защищенными для наследования. StaticGlow3D будет служить суперклассом для классов BackgroundGlow3D и BackgroundNoise3D. Его конструктор вызывает super (), чтобы назначить имя для DisplayObject3D. Затем устанавливается свойство _viewport и вызывается init ().


Метод init () создает изображение, используемое для эффекта. Добавьте код ниже после конструктора:

Как видно из комментариев, 3D-плоскости предоставлен специальный материал из двух растровых данных. Вероятно, проще, если мы просто использовали объект VectorShape3D и применили к нему размытие, но это тоже хорошо. Позже вы увидите, как мы можем использовать этот же принцип и создавать статический эффект с выцветшими углами.


Как только все будет подготовлено, все, что нам нужно сделать, — это внешний контроль за постепенным исчезновением эффекта. Добавьте 2 последних метода:

Метод flash () вызывается до появления меню на сцене. Он проверяет значение $ sideway и анимирует на основе этого значения. Если значение $ sideways равно true, например, когда мы заходим в меню настроек, свойство scaleX свечения сжимается, а затем переходит в нормальное состояние. Если в качестве значения по умолчанию оставить $ sideways — false, как, например, при переходе в главное меню, свойство scaleY свечения сжимается, а затем переходит в нормальное состояние. Второй публичный метод, fadeOut (), делает противоположное и вызывается при закрытии меню. Только на этот раз изображение истончается, а затем исчезает.


Сначала перейдите в начало класса, где объявлены свойства, и добавьте _staticGlow в качестве свойства экземпляра. Войдите в метод init () тестера и добавьте вызов addStaticGlow () перед вызовом addMainMenu (). Затем добавьте приведенный ниже код после метода init ():

Затем перейдите внутрь методов addMainMenu () и onMenuExitComplete (). Добавьте вызов _staticGlow.flash () после вызова метода startIntro () MainMenu3D. Затем перейдите в начало метода navigateTo () и добавьте вызов _staticGlow.fadeOut (). Методы должны выглядеть следующим образом:

Запустите программу, и вы должны получить результат, показанный по ссылке здесь . Хорошо! Далее идет класс StaticNoise3D.


Если вы хотите увидеть этот эффект в действии, перейдите по ссылке предварительного просмотра, размещенной выше, и измените Качество на лучшее в меню настроек. Этот класс будет расширять StaticGlow3D и применять некоторые модификации. Вот список:

  1. нарисовать изображение для использования в качестве статического шума // так же, как суперкласс
  2. обеспечить внешнее управление для анимации входа и выхода // так же, как суперкласс
  3. есть 2 различных способа анимировать эффект и соответствовать тому, как открывается активное меню // то же, что и суперкласс
  4. обеспечить внешний доступ для вызовов обновления для применения случайного шума к BitmapData для эффекта // дополнительная ответственность

Создайте новый класс и назовите его BackgroundNoise3D, пусть он расширяет StaticGlow3D.
Скопируйте приведенный ниже код и замените на него содержимое нового класса:

Поскольку мы используем ООП, нам нужно импортировать только то, что нам нужно, чтобы изменить класс. Конструктор класса принимает те же 2 параметра и передает их обоим в StaticGlow3D.


Как показано в списке обязанностей, все очень похоже на суперкласс, за исключением того, как создается эффект и 1 дополнительная ответственность. Метод update () позаботится о применении шума к BitmapData, который используется для эффекта. Это, я думаю, самый маленький класс в этом проекте. Добавьте код ниже:

Вы можете получить больше информации о методе BitmapData.noise () здесь . Вот и все. BackgroundNoise3D закончен! Еще один хороший пример силы ООП.


Внутри метода init () тестера добавьте вызов addBackgroundNoise () чуть ниже вызова метода addStaticGlow. Скопируйте код ниже после фактического метода addStaticGlow ():

Далее, он управляется так же, как StaticGlow3D. Добавьте коды ниже в соответствии с комментарием, размещенным над каждым кодом:

Наконец, нам нужно повторно вызывать его метод update (), чтобы отразить изменения, примененные к шумовому эффекту. Добавьте приведенный ниже код в метод onRenderTick ():

Не забудьте объявить _backgroundNoise как свойство экземпляра типа BackgroundNoise3D в верхней части класса. Теперь вы можете запустить программу. Это должно выглядеть как ссылка здесь .


Мне все еще казалось, что меню было неполным, поэтому я подумал, почему бы не добавить полосатый фон, который светится до того, как меню оживут. Его список обязанностей:

  1. нарисовать изображение, чтобы использовать его как полосатое свечение // изменено из суперкласса
  2. обеспечить внешнее управление для анимации входа и выхода // изменено из суперкласса
  3. воспроизводить звук каждый раз, когда применяется эффект // дополнительная функциональность

Создайте новый класс и назовите его BackgroundGlow3D. Это тоже расширит StaticGlow3D. Скопируйте код ниже, заменив все в новом классе:

Здесь происходит больше импорта из-за небольшого количества изменений в изображении для эффекта. Но конструктор остается идентичным.


Размеры одинаковы, но на этот раз мы рисуем линии с пробелами между ними в BitmapData. Добавьте код ниже после конструктора:

Смотрите комментарий в коде, где написано «начало изменений»? Эта часть добавляет спрайты с нарисованными на них линиями и добавляет их в _parentSprite. _ParentSprite затем используется в качестве фона для BitmapData, используемого в качестве материала для 3D-плоскости.


Этот эффект будет иметь только один внешний контроль. Метод flash () будет вызываться каждый раз при загрузке меню. В отличие от эффекта статического свечения, который остается с меню, этот эффект исчезнет, ​​как только он начнет мигать. Это делает метод fadeOut () неактуальным. Добавьте код ниже:

Переопределенный из суперкласса, параметр $ sideways является обязательным, но не имеет приложения. Модификация здесь также включает воспроизведение звукового эффекта backgroundFlash, загруженного из экземпляра CustomLoader. Это завершает класс BackgroundGlow3D. Поскольку мы не переопределяли метод fadeOut (), он все еще доступен для этого подкласса. Если вы хотите полностью отключить его, просто переопределите метод и оставьте его пустым, не передавая вызов суперклассу.


Вернитесь в метод init () тестера и добавьте вызов addBackgroundGlow () чуть ниже вызова метода addBackgroundNoise (). Скопируйте приведенный ниже код после метода addBackgroundNoise ():

Затем перейдите к методам addMainMenu () и onMenuExitComplete () и добавьте следующий код:

Снова убедитесь, что _backgroundGlow объявлен как свойство экземпляра типа BackgroundGlow3D в верхней части класса. каждый раз, когда вызывается метод startIntro () MainMenu, также должен вызываться метод flash () для всех эффектов. Теперь запустите программу. Результат можно посмотреть здесь .

Теперь это пронизано эффектами! =) Позже мы добавим опцию для включения или выключения BackgroundNoise3D.

Сделайте перерыв и вернитесь, когда будете готовы приступить к созданию первого из двух подменю, AboutMenu3D.


Этот DisplayObject3D будет модифицированным подклассом MainMenu3D. Он будет содержать скрытую 3D-текстовую прокрутку, 2 кнопки для прокрутки этого текста и кнопку «Назад» для возврата в главное меню. Его список обязанностей:

  1. создать 2 границы для использования в качестве оболочки для содержимого этого меню // так же, как суперкласс
  2. создать и добавить 3 кнопки и добавить слушателей для них // модифицированные из суперкласса
  3. подготовиться к вводной анимации // модифицировано из суперкласса
  4. добавить эффекты и анимацию // модифицировано из суперкласса
  5. добавить 3D прокрутку текста // новая ответственность
  6. добавить маску для 3D-прокрутки текста // новая ответственность
  7. обеспечить внешнее управление для воспроизведения анимации вступления и выхода // так же, как суперкласс
  8. управлять активацией и деактивацией кнопок // так же, как суперкласс
  9. отправить пользовательское событие, вызванное кнопкой возврата, чтобы UserInterface3D мог загрузить MainMenu3D назад // дополнительная ответственность

Вернитесь сюда по ссылке предварительного просмотра и нажмите кнопку «О программе», чтобы открыть это меню. Он выглядит проще, чем MainMenu3D из-за меньшего количества кнопок, но его внутренняя работа немного сложнее. Создайте новый класс и назовите его AboutMenu3D. Пусть это продлит MainMenu3D. Когда файл класса открыт, просто скопируйте и вставьте приведенный ниже код, заменив содержимое класса.

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


Чтобы изменить содержимое этого меню, свойства должны быть изменены из метода init (). Добавьте код ниже после конструктора:

Новые значения назначаются для унаследованных свойств, которые необходимо изменить перед вызовом метода init () суперкласса. О новых обязанностях заботятся. Далее мы переопределяем метод createFrame (), чтобы изменить внешний вид двух границ. Добавьте код ниже после метода init ():

Границы нарисованы совершенно иначе, чем у суперкласса. Затем добавьте модифицированный метод addButtons ():

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

Это заботится обо всех унаследованных методах, запущенных из init (). Теперь о двух дополнительных функциях. Добавьте код ниже:

Метод вызывается перед createText (), чтобы сделать маску доступной и готовой. 3D-плоскость создается с той же шириной, что и границы и высотой 550. Чтобы использовать 3D-объект в качестве маски, нам нужно получить доступ к его свойству ViewportLayer. Затем добавьте метод createText ():

Это похоже на то, как мы создали текст для Button3D или UIComponent3D. Маскирование применяется путем назначения ViewportLayer 3D-плоскости в качестве маски для ViewportLayer Text3D.


Прямо сейчас, когда вызывается startIntro (), 2 границы и 3 кнопки будут анимироваться так же, как MainMenu3D. Добавьте код ниже, чтобы добавить 3D-текст при запуске вступления:

Метод initializeButtons () вызывается, когда границы достигают своих открытых позиций. Проверьте метод startIntro () в MainMenu3D для обновления. Здесь у нас есть метод суперкласса для обработки 3 кнопок, а затем анимация трехмерного текста. Затем добавьте модифицированный метод showButtons (), вызываемый из initializeButtons () MainMenu3D:

Здесь мы делаем то же самое с суперклассом, чтобы убедиться, что для _scrollDown и _scrollUp установлены значения false. Мы должны были сделать это здесь, потому что другие 2 кнопки используются для прокрутки и используют слушатели onButtonOver (). Если эти слушатели будут вызваны функцией showButtons (), трехмерный текст начнет прокручиваться.


Все обрабатывается внутри, кроме случаев, когда нажата кнопка «Назад». Добавьте код ниже:

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

Эти два метода присваивают значение свойствам _scrollUp и _scrollDown, которые будут использоваться в качестве маркера при прокрутке текста. Вы увидите позже, когда мы перейдем к дополнительному методу onUpdate ().


Ничего особенного для метода startExit (). Мы просто делаем 3D-текст невидимым, а затем оставляем суперклассу все остальное. Метод hideButtons () переопределяется, чтобы убедиться, что для _scrollUp и _scrollDown снова установлено значение false. Если этого не сделать, трехмерный текст будет прокручиваться вниз, пока меню удалено. Добавьте код ниже:

Если вы не уверены, как эти два метода взаимодействуют, вернитесь и просмотрите метод startExit () MainMenu3D.


Как и BackgroundNoise3D, визуальные изменения могут быть применены только из метода update ().

Этот метод будет вызываться повторно из метода onRenderTick () UserInterface3D. Он постоянно проверяет значения _scrollUp и _scrollDown и корректирует положение «y» трехмерного текста. Это завершает класс AboutMenu3D.


Вернитесь к методу init () тестера и закомментируйте вызовы addBackgroundNoise и addMainMenu, затем добавьте вызов addAboutMenu () в нижней части метода. Затем добавьте код ниже метода init ():

Не забудьте объявить _aboutMenu как свойство экземпляра типа AboutMenu3D в верхней части класса. Как вы можете видеть, это очень похоже на реализацию MainMenu3D. На этот раз мы слушаем только MainMenu3D.BACK_TO_MAIN и масштабируем два эффекта на 1,5 процента от первоначального размера. Затем измените метод navigateTo (), как показано ниже, с комментариями:

Обязательно закомментируйте вызов вызова метода _backgroundNoise.fadeOut (), так как на этот раз мы его не создаем. Назначьте новую цель перехода для события MainMenu3D.BACK_TO_MAIN в нижней части оператора switch.

OnMenuExitComplete () будет действовать точно так же для AboutMenu3D, благодаря ООП, но вам также необходимо закомментировать вызов _backgroundNoise.flash () внутри него.

Наконец, зайдите в метод onRenderTick () и измените код в соответствии с комментариями, как показано ниже:

Теперь запустите приложение, и вы должны увидеть что-то вроде этого .


Мы дошли до нашего последнего меню. Безусловно, это меню более сложное, чем два других. Но чтобы этот класс работал, нам нужно создать 3 новых класса — CheckBox3D, RadioButton3D и ButtonGroup3D. Итак, давайте выпрыгнем и поработаем над этими компонентами. Давайте начнем с CheckBox3D. Вы увидите подробную информацию о SettingsMenu3D, когда мы перейдем к шагу 75.


Перейдите по ссылке предварительного просмотра и играйте с полноэкранным флажком в меню настроек. Включите его, затем выключите снова, нажав на него. После его включения вы также можете выключить его, нажав клавишу выхода. Он несколько отличается от Button3D — он использует координаты для рисования по-разному, кнопка остается на своей оси ‘z’, когда мышь находится над ней, экземпляр будет иметь дополнительную логическую переменную для хранения значения ее текущего состояния, кнопка будет иметь дополнительные внешние элементы управления, чтобы включить или выключить ее. Его список обязанностей:

  1. играть звуковые эффекты для мыши и мыши. // унаследованы
  2. добавить интерактивную плоскость, которая будет вызывать события мыши. // унаследованы
  3. применять эффекты для наведения мыши, мыши и щелчка мыши. // модифицированный
  4. обеспечить внешнее управление для добавления и удаления слушателей событий мыши // унаследованных
  5. обеспечить внешнее управление для удаления слушателей щелчка мыши // наследуется
  6. обеспечить внешнее управление для включения или выключения кнопки // дополнительные функции
  7. нарисовать флажок с помощью Vectorshape3D // модифицировано из UIComponent3D
  8. хранить свое собственное состояние и предоставлять к нему доступ извне // новая функциональность

Создайте новый класс с именем CheckBox3D, пусть он расширяет Button3D. Замените код в этом коде ниже:

Инстанциация такая же, за исключением значений внутри переменной _coordinates. Для рисования мы будем использовать метод Graphics3D.drawRoundRect () вместо методов moveTo () и lineTo (), которые мы использовали для суперкласса. Чтобы сохранить единообразие, мы сохраним массив Number2D _coordinates и просто не будем использовать его свойство ‘y’, установив для них значение 0. Смотрите комментарии для обозначения.


Как только экземпляр создан и метод init () вызван извне, запускаются следующие 3 метода. Добавьте модифицированный метод setDimensions () после конструктора:

Затем добавьте модифицированный метод createInterface ():

Здесь мы полностью откажемся от вызова метода createInterface () суперкласса. Вместо этого он вызывает новый метод drawButton (), а затем возвращается к использованию метода addInteractivePlane () суперкласса. Затем добавьте модифицированный метод createText ():

После разрешения суперклассу создавать текст, CheckBox3D вступает во владение и изменяет его местоположение и масштаб.


Этот метод сначала вызывается методом createInterface () и каждый раз, когда вызывается onObjectClick (). Он отображает флажок на основе текущего значения _state.

Он должен напоминать вам о методе createInterface () UIComponent3D. Смотрите комментарии для его различий.


Для наведения мыши мы хотим, чтобы флажок все еще светился, но оставался в исходном положении. Добавьте переопределенный метод onObjectOver ():

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

Во-первых, _state устанавливается в противоположное значение; затем вызывается метод drawButton (), чтобы перерисовать флажок. Затем он отправляет событие и воспроизводит назначенный звук для нажатия кнопок. Для метода onObjectOut () не требуется никаких модификаций, поэтому мы пропустим это здесь.


Вот вам и дополнительная функциональность для внешнего или выключения кнопки. Метод turnOn () установит значение _state в true, затем вызовет метод drawButton ():

Затем добавьте соответствующий метод turnOff ():

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

И наконец, добавьте доступ к текущему состоянию флажка:


Вернитесь к методу init () внутри класса Tester и закомментируйте вызовы методов addAboutmenu (), addBackgroundGlow () и addStaticGlow (). Еще в методе init () добавьте вызов addCheckbox () внизу. Зайдите в метод onRenderTick () и закомментируйте вызов _aboutMenu.update (). Затем добавьте новый метод ниже метода init ():

Очень важно изменить значение lineAlpha, помните, по умолчанию это 0 из суперкласса UIComponent3D. Затем добавьте обратный вызов для прослушивателя checkboxClicked:

Мы будем использовать эту информацию для изменения полноэкранного режима позже. А пока давайте просто сделаем трассировку. Теперь запустите приложение, и вы должны увидеть что-то похожее на картинку ниже. Трассировка должна показывать значение состояния флажка при каждом нажатии флажка. Положение немного смещено, но мы исправим это, когда добавим его в качестве компонента для меню настроек.



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

Создайте новый класс с именем RadioButton3D, сделайте так, чтобы он расширял CheckBox3D, и сохраните его. Замените содержимое нового класса на код ниже:

Будет только 3 визуальные модификации от CheckBox3D, поэтому список обязанностей одинаков. Во-первых, нам нужно изменить масштаб и положение текста / метки. Во-вторых, мы используем метод Graphics3D.drawCircle () вместо Graphics3D.drawRoundRect () для рисования переключателя. И третье, поскольку мы используем Graphics3D.drawCircle (), метод setDimensions () необходимо будет изменить, чтобы использовать то же значение для его свойств width и height. Добавьте код ниже для переопределенного метода setDimensions () после конструктора:

Затем добавьте модифицированный метод drawButton ():

Теперь добавьте модифицированный метод createText ():

И это завершает RadioButton3D. Слава Богу за наследство. Вы можете протестировать его, если хотите, просто измените часть, где написано новое CheckBox3D, с новым RadioButton3D внутри метода addCheckBox () в Tester, и все готово. Или вы можете подождать, пока мы не создадим ButtonGroup3D, чтобы протестировать группу радиокнопок, которые мы делаем дальше.


Этот класс будет действовать как менеджер и контейнер для группы переключателей. Он принимает 4 обязательных параметра и 1 необязательный при создании экземпляра. Параметры: имя / метка для группы, область просмотра, массив имен кнопок и состояние по умолчанию. Последний необязательный параметр был создан для предоставления возможности выравнивания кнопок по вертикали или по горизонтали. К сожалению, из-за нехватки времени я смог применить только горизонтальное выравнивание. Я оставлю это вам, чтобы закончить с вертикальным вариантом. Ниже приведен список обязанностей.

  1. создать текст для использования в качестве имени и метки
  2. создать набор радиокнопок, которые будут работать вместе как группа
  3. управляйте кнопками так, чтобы только одна находилась во включенном состоянии (все остальные находятся в выключенном состоянии)
  4. отправлять событие STATE_CHANGED при изменении состояния группы (т. е. при включении другой кнопки)
  5. держать значение текущего состояния группы
  6. заставьте каждую кнопку светиться так же, как их суперкласс, когда меню собирается закрыться

Создайте новый класс с именем ButtonGroup3D и сделайте так, чтобы он расширял DisplayObject3D. Скопируйте код ниже, чтобы заменить весь контент внутри нового класса:

Опять же, как и другие классы во время создания экземпляров, параметры передаются и сохраняются, затем вызывается метод init () для подготовки содержимого компонентов.


Метод init () вызывает два других метода для подготовки текста и кнопок для группы. Добавьте код ниже после метода конструктора:

Следующий метод для создания текста такой же, как мы сделали для других классов, только позиция и масштаб были изменены. Добавьте код ниже метода init ():

Следующий. добавьте метод addButtons ():

Верхняя часть цикла проходит через количество имен кнопок, сохраненных в массиве _buttonNames. Затем он устанавливает визуальные свойства каждой кнопки и добавляет их в качестве дочерних одновременно, сохраняя ссылку для каждого в _buttonArray. Средняя часть метода проверяет, соответствует ли имя кнопки назначенному состоянию по умолчанию, которое также было передано в конструкторе. Если это так, кнопка включается, а затем отключается от прослушивания событий. Если нет, кнопка остается в выключенном состоянии и активируется для прослушивания событий. Последняя часть просто выравнивает кнопки по горизонтали. Каждой кнопке назначается слушатель, который срабатывает только при активной кнопке. ButtonGroup3D обработает это внутренне перед отправкой.


Ниже приведен обратный вызов, который будет обрабатывать события нажатия для всех активных кнопок. Добавьте код после метода addButtons ():

Здесь состоянию для группы кнопок назначается имя активной кнопки, по которой была нажата кнопка. Затем все кнопки проходят через петлю, чтобы увидеть, была ли нажата кнопка. Если это так, он отключается от прослушивания щелчков, если кнопка не совпадает с кнопкой, которая была нажата, она отключается и снова активирует ее для событий щелчков. Когда цикл завершается, отправляется событие STATE_CHANGED, информирующее его родительский контейнер — SettingsMenu3D.


Метод flash () заставит мигать все кнопки, когда меню будет закрыто. Вы увидите, как это применяется, когда мы доберемся до SettingsMenu3D. Добавьте код ниже:

И, наконец, добавьте код ниже, чтобы обеспечить доступ к текущему состоянию группы кнопок:


Вернитесь к классу Tester внутри метода init () и закомментируйте вызов addCheckbox (), затем добавьте вызов addButtonGroup () под ним. Вставьте приведенный ниже код после метода init ():

Прямо сейчас при текущей настройке лучше всего использовать от 3 до 5 символов для надписей кнопок. Когда создается экземпляр ButtonGroup3D, ему передается имя для группы кнопок, область просмотра, массив имен кнопок в строковом формате, которые будут использоваться в качестве имен для каждой кнопки, а также в качестве различных состояний для группы кнопок, и состояние по умолчанию, которое может быть любая из 3 строк внутри массива кнопок. После создания экземпляра необходимо прослушать пользовательское событие ButtonGroup3D.STATE_CHANGED, чтобы узнать, когда была нажата активная радиокнопка. Остальные помещают экземпляр ButtonGroup3D в центр и добавляют его в сцену. Затем добавьте обратный вызов для слушателя события onStateChange:

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


Как и AboutMenu3D, этот класс также будет наследоваться от MainMenu3D. Это будет наше последнее меню, и как только мы это сделаем, мы поработаем над классом UserInterface3D, чтобы наконец собрать все воедино. Это меню позволит пользователю изменить несколько внутренних настроек флеш-плеера, добавить или удалить эффект и сохранить выбранный уровень для игры. Его список обязанностей:

  1. создать 2 границы для использования в качестве оболочки для содержимого // изменено
  2. создать и добавить кнопки и добавить слушателей для них // изменено
  3. подготовиться к вводной анимации // модифицировано
  4. добавить эффекты и анимацию // модифицировано
  5. обеспечить внешнее управление для воспроизведения анимации вступления и выхода // так же, как суперкласс
  6. управлять активацией и деактивацией кнопок // изменено
  7. отправлять пользовательские события, запускаемые кнопками, чтобы UserInterface3D мог применить изменения к настройкам флэш-плеера или удалить эффект. // модифицированный
  8. сохранить уровень игры доступным для внешнего доступа // дополнительные функции
  9. сохранить качество сцены, доступное для внешнего доступа // дополнительные функции

Создайте новый класс с именем SettingsMenu3D и сделайте так, чтобы он расширял MainMenu3D. Замените содержимое класса с кодом ниже:

Если вы отметите это меню из ссылки просмотра здесь , вы увидите , что он содержит 1 флажок , который переключает режим полноэкранного, группы кнопок 2 радио , которые обрабатывают качество стадии и уровень игры, и 1 кнопку назад , чтобы вернуться в главное меню , Первые 3 свойства в верхней части объявления класса будут служить уровнями игры для нашей программы. Закрытое свойство _level будет всегда хранить 1 из этих 3 уровней и будет иметь значение по умолчанию LEVEL_NORMAL. Свойство _quality будет содержать значение качества сцены и по умолчанию будет StageQuality.MEDIUM. Последние 2 свойства будут содержать экземпляры ButtonGroup3D, 1 для качества сцены и другое для уровня игры. Конструктор должен только передать информацию суперклассу.


Как только метод init () вызывается конструктором суперкласса, мы переопределяем его из SettingsMenu3D и вносим изменения в некоторые унаследованные свойства. _ButtonPosY назначается только 2 позициям «y» для кнопок, которым следует следовать, _buttonTitles назначается новый массив, содержащий новую информацию, которую необходимо создать в качестве кнопок. Затем вызывается метод init () суперкласса для продолжения процесса. Добавьте код ниже метода конструктора:

Из метода init () суперкласса вызываются следующие 3 метода. Первым является createFrame (), который переопределяется для изменения формы и цвета границ меню. Добавьте код после метода init ():

Метод addButtons () был немного изменен. Я разделил метод на две части, чтобы его было легче понять. Он начинается с подготовки _buttonArray для хранения ссылок на кнопки, которые мы собираемся создать. _buttonTitles затем циклически просматривается и проверяется, соответствует ли имя ‘<<‘. Если это так, экземпляр Button3D создается и добавляется в центр меню. Его текст центрируется вручную внутри визуального представления кнопки. Если имя не соответствует «<<», вместо этого создается экземпляр CheckBox3D, который помещается в верхней части меню. Цвета экземпляра также изменяются перед вызовом метода init () кнопки. Находясь в цикле, каждой кнопке назначается прослушиватель для кликов, расположенный на оси ‘y’ на основе значения текущей итерации в _buttonPosY,сохранил ссылку в _buttonArray и добавил ее в качестве дочерних элементов SettingsMenu3D. Вторая часть добавляет 2 ButtonGroup3D для контроля качества сцены и уровня игры. У нас также есть другой слушатель, назначенный для этих групп кнопок, так как они должны обрабатываться по-разному. Добавьте полный код дальше:

И метод setMenuEffect (), последний метод, вызываемый init (). Мы переопределяем это здесь и не применяем никакого эффекта. Ребята, я передам это как дополнительное домашнее задание, если вы хотите использовать DistortionEffect для SettingsMenu3D. Помните, что для применения фильтра требуется массив слоев области просмотра. Добавьте код ниже:


Поскольку две границы открываются в горизонтальном движении, они расположены немного иначе, чем мы сделали это для суперкласса. И _gameLevel, и _stageQuality полностью прозрачны и готовы к вводной анимации. Добавьте код ниже после метода setMenuEffect ():

Метод startIntro () отличается от суперкласса только тем, как открываются 2 границы. Здесь мы перемещаем границы ‘x’, чтобы отодвинуть их друг от друга. Добавьте следующий код:

Метод initializeButtons () не нужно менять, поэтому мы оставляем его как есть в суперклассе.

Метод showButtons () вызывает свой супер метод, а затем вступает во владение, чтобы управлять вступлением для 2 ButtonGroup3D. Добавьте следующий код:


Метод onButtonClick () будет обрабатывать щелчки для полноэкранного флажка и кнопки возврата. Он имеет ту же функциональность, что и суперкласс. Если имя нажатой кнопки «<<», оно отправляет MainMenu.BACK_TO_MAIN и запускает анимацию выхода. Если был установлен полноэкранный флажок, он отправляет InteractiveScene3DEvent.OBJECT_CLICK. Переключение в полноэкранный режим будет осуществляться через UserInterface3D, поэтому все, что мы здесь делаем, это информируем его о событии. Добавьте код ниже:

Метод onStateChange () будет обрабатывать щелчки для двух групп кнопок. Здесь он проверяет состояние цели события и отвечает соответственно. Затем, если имя цели — «Качество», оно передает событие вверх для использования UserInterface3D. Нам не нужно распространять событие, если оно пришло с уровня, так как оно будет проверено классом Основной документ перед загрузкой образца игрового спрайта. Поэтому мы просто проследим это здесь для тестирования. Добавьте код ниже:


При нажатии кнопки «Назад» вызывается метод startExit () суперкласса. Нам не нужно переопределять его здесь, поскольку он будет работать так же для SettingsMenu3D, как и для суперкласса. Как только функция startBittons () вызывается функцией hideButtons (), мы высвечиваем 2 группы кнопок, поэтому они выходят так же, как и другие кнопки, и затем становятся невидимыми. После обработки двух групп кнопок он передает вызов суперклассу, чтобы снять флажок и кнопки возврата.

Метод hideObject () также просто наследуется без изменений и после завершения вызывает вызываемый здесь метод closeNav (). Опять же, он отличается от суперкласса только тем, как закрываются 2 границы. Добавьте код ниже:


Вот несколько дополнительных функций для SettingsMenu3D. Добавьте код ниже:

Эти 3 метода обеспечивают внешний доступ к 3 конфигурациям, хранящимся в SettingsMenu3D. К ним будут обращаться классы Main и UserInterface3D. Затем добавьте метод exitFullScreen ():

Этот метод вызывается, когда пользователь нажимает клавишу выхода, таким образом, даже если SettingsMenu3D не является активным меню, его все равно можно отключить, если пользователь решит выйти из полноэкранного режима. На следующем шаге вы увидите, как это используется, когда мы протестируем SettingsMenu3D. У нас будет класс Main document для прослушивания этого события, чтобы мы могли синхронизировать полноэкранный флажок, даже если UserInterface3D не активен на сцене.


Хорошо, есть довольно много модификаций, которые мы должны сделать, чтобы протестировать SettingsMenu3D. Мы будем прокладывать путь сверху. Зайдите в объявление пакета Tester по импорту и добавьте следующий код:

Далее перейдите к методу конструктора. Добавьте код ниже после вызова startRendering ():

Это событие сообщит нам, когда сцена будет доступна для доступа. Затем, после конструктора, добавьте метод обратного вызова ниже:

Прослушиватель FullScreenEvent будет использоваться для информирования SettingsMenu3D о том, чтобы полноэкранный флажок был выключен. Метод setStageQuality () устанавливает качество сцены на основе стандартного stageQuality в SettingsMenu3D. Добавьте два метода, которые отвечают на них:

Когда вы посмотрите на класс документа Main, вы увидите, что экземпляр Tester создается перед его добавлением на сцену. Поэтому применение изменений качества сцены сразу после создания экземпляра SettingsMenu3D не будет работать. «Сценический» объект просто еще не будет доступен. Поэтому зайдите в метод init () для Tester и раскомментируйте вызовы методов addStaticGlow () и addBackgroundGlow (). Затем закомментируйте вызов addButtonGroup () и добавьте вызов addSettingsMenu () под ним. Затем добавьте приведенный ниже код после метода init ():

Убедитесь, что _settingsMenu объявлена ​​как переменная экземпляра типа SettingsMenu3D.

У нас есть 4 разных слушателя, назначенных экземпляру SettingsMenu3D. Метод navigateTo () запускается при нажатии кнопки «<<» внутри SettingsMenu3D. Метод onStateChange () вызывается, когда группа кнопок с именем «Quality» меняет состояние и заменяет содержимое метода onStateChange (), как показано ниже. Метод toggleFullscreen () запускается всякий раз, когда устанавливается полноэкранный флажок, а метод onMenuExitComplete () запускается, когда меню завершает анимацию выхода. Мы устанавливаем scaleX для _staticGlow и _backgroundGlow в 1,25 раза больше их исходного размера, чтобы соответствовать меню. После вызова метода startIntro () мы вызываем методы flash () для _staticGlow и _backgroundGlow, передавая логическое значение true, чтобы они мигали по горизонтали.Добавьте 2 дополнительных метода обратного вызова для SettingsMenu3D ниже:

Нам нужно проверить, доступно ли свойство stage, прежде чем изменять его состояние отображения. Мы применяем это здесь, чтобы подготовить это, когда мы используем это для UserInterface3D. Там, если игра активна, UserInterface3D будет удален со сцены и временно потеряет свое свойство сцены. Метод onStateChange () не должен проверять этап, поскольку он может быть запущен только из SettingsMenu3D. Наконец, перейдите к методу onMenuExitComplete () и передайте значение true для вызова метода _staticGlow.flash (). Сделайте то же самое для вызова метода _staticGlow.fadeOut () внутри метода navigateTo ().

Теперь запустите программу. Вы должны получить результат, как ссылка здесь . Для тех, кто использует Flash IDE, полноэкранный режим не будет работать при запуске из Flash. Вам придется открыть SWF-файл напрямую с помощью Flash Player.


Увы, финальный класс для нашего проекта. Класс UserInterface3D — самый большой из них. Он будет наследоваться от BasicView, как и класс Tester. Думайте об этом классе как о главном контроллере, все будет обрабатываться этим классом. Вернитесь и проверьте ссылку здесь для полнофункционального предварительного просмотра. Поиграйте с ним на мгновение, чтобы почувствовать, как UserInterface3D управляет всем. Вот его список обязанностей:

  1. настроить сцену — т.е. установить режим сортировки на индексную сортировку, установить свойства камеры и т.д …
  2. создайте все меню и загрузите каждое из них соответствующим образом
  3. управлять всеми событиями из 3 меню и применять изменения для их обозначения — т.е. переключить полноэкранный режим, сообщить классу основного документа, чтобы загрузить игру
  4. обрабатывать позицию 1 большого DisplayObject3D, в котором будут размещены все 3 меню
  5. добавьте 3 эффекта — фоновый шум, фоновое свечение и статическое свечение и управляйте ими
  6. обеспечить внешнее управление для загрузки главного меню при удалении игрового спрайта
  7. обеспечить внешний контроль для управления полноэкранным флажком в SettingsMenu3D, когда полноэкранный режим отключен, когда игровой спрайт активен

Я разделил класс на две большие части: инициализацию и обработку событий. Создайте новый класс с именем UserInterface3D и сделайте так, чтобы он расширял BasicView. Вставьте код ниже, заменив весь код внутри нового класса:

У этого класса довольно много свойств, но мы рассмотрели большинство из них в классе Tester. Смотрите комментарии для описания свойств. Конструктор настроен на запуск метода init (), только когда сцена доступна. Это позволяет избежать ошибок при попытке доступа к объекту «stage».


Как только метод init () вызывается, он запускает серию методов, которые по ответственным причинам нарушают процесс инициализации. Добавьте код ниже после конструктора:

Эти методы не являются взаимозаменяемыми, вы столкнетесь с ошибками, если попытаетесь вызвать setStageQuality () перед initializeInterface (). Добавьте метод setUpScene () после метода init ():

Здесь вы можете применить модификации для камеры, сцены и области просмотра. Здесь мы удостоверяемся, что камера не смотрит ни на один DisplayObject3D. Для области просмотра режим сортировки и интерактивные свойства изменяются в соответствии с нашими требованиями. Здесь мы также добавляем 1 DisplayObject3D, в котором будут размещены 3 меню. Я решил сделать это, чтобы лучше контролировать 3 меню. Эффекты будут добавлены непосредственно в сцену, так как им не нужно будет перемещаться, как в меню. Затем добавьте initializeEffects () после метода setUpScene ():

Этот метод просто добавляет 3 эффекта в сцену с небольшими различиями для их положений «z». Добавьте следующий код для метода initializeInterface () следующим образом:

InitializeInterface () создает экземпляры всех меню, а затем загружает экземпляр MainMenu3D в сцену. Я расскажу больше об отдельных методах, когда мы перейдем к ним. Затем добавьте метод setStageQuality () после initializeInterface ():

Здесь для качества рабочей области задано стандартное качество сцены для экземпляра SettingsMenu3D. Этот метод вызывается каждый раз, когда экземпляр SettingsMenu3D отправляет событие ButtonGroup3D.STATE_CHANGED. Он также проверяет, установлено ли качество сцены на «ЛУЧШИЙ»; если это так, экземпляр BackgroundNoise () добавляется в сцену, если нет, он удаляется из сцены. Мы предоставляем пользователю возможность включить или отключить его, так как он интенсивно использует процессор.


Давайте теперь перейдем к добавлению всех меню. Во-первых, initMainMenu (). Добавьте код ниже:

Все так же, как мы их использовали в классе Tester, за исключением позиции «x», которую мы применяем к каждому из меню. Также обратите внимание, что мы не добавили меню в _grandObject3D. Это будет сделано, когда вызывается addInteractivity (), передавая правильное меню для загрузки. Затем добавьте метод initSettingsMenu ():

Позиция ‘x’ установлена ​​на абсолютное значение, потому что _grandObject3D будет перемещаться в направлении истинного значения. Хорошим объяснением было бы: «если текущая позиция« x »равна 0, то есть где _mainMenu находится, и нам нужно перейти к позиции« x »_settingsMenu, равной 2000, _grandObject3D переместится на позицию« x »с -2000 центрирования _settingsMenu в сцена.» Помните, что все меню содержатся внутри _grandObject3D с разными позициями ‘x’. Затем добавьте initAboutMenu ():

После добавления всех меню поток событий возвращается к методу initializeInterface () и вызывает addInteractivity (). Добавьте код ниже:

Вот как _mainMenu в основном загружается на сцену. Этот метод также вызывается при каждом нажатии кнопки для изменения меню. Он работает с методом loadTargetMenu (), который обсуждается ниже в разделе обработки событий. Здесь свойству _currentMenu назначается меню, которое необходимо загрузить. _grandObject3D затем добавляет это меню как единственный дочерний элемент, чтобы сделать его доступным для сцены. Затем меню добавляется слушателем, когда оно полностью закрылось. Эта информация позволит загружать меню замены только после полного закрытия предыдущего меню. После вызова метода startIntro () он проверяет тип меню; если он имеет тип SettingsMenu3D, он сообщает _staticGlow и _backgroundNoise для анимирования по горизонтали; если тип меню — что-то еще, два эффекта будут анимированы по вертикали. И это завершает раздел инициализации.


С этого момента остальные функции UserInterface3D запускаются событиями. Добавьте код, который отвечает при нажатии полноэкранного флажка в _settingsMenu:

Далее, поскольку полноэкранный режим может измениться, когда пользователь нажимает клавишу escape, когда игровой спрайт активен (это означает, что экземпляр UserInterface3D был временно удален как дочерний элемент основного документа), нам нужно будет сообщить _settingsMenu, чтобы снять флажок полноэкранный флажок, когда это произойдет. Добавьте код ниже:

Теперь, когда экземпляр класса Main document обнаруживает, что пользователь вышел из полноэкранного режима, экземпляр SettingsMenu3D информируется. Мы добавим этот слушатель в класс основного документа, когда закончим сборку UserInterface3D. Затем добавьте неявный метод get уровня:

Это позволит Основному документу получить доступ к уровню, выбранному в _settingsMenu, и проинформировать об этом игровой спрайт. Затем добавьте метод navigateTo ():

Это работает так же, как мы использовали его для класса Tester. Здесь мы используем его для масштабирования эффектов и изменения значений свойств _closeApp и _loadGame. Оба будут использоваться методом loadTargetMenu (), обсуждаемым далее. Добавьте код ниже:

Этот метод вызывается после полного выхода из текущего меню. Вот почему проигрыватель webpage / standAlone закрывается только после того, как меню исчезает, когда вы нажимаете кнопку выхода. Если значение _loadGame равно true, отправляется UserInterface3D.START_GAME, чтобы сообщить основному документу о загрузке игрового спрайта. Как только событие отправлено, _loadGame снова устанавливается в false и метод преждевременно завершается. Игра Sprite будет загружена, а UserInterface3D будет удалена со сцены. Это также метод, который основной документ будет вызывать для загрузки экземпляра UserInterface3D обратно на сцену.

Затем добавьте метод onRenderTick () ниже:

То же приложение, что и в Tester. Но вместо этого камера остается на том же месте, а все остальное вращается и перемещается.


Как я уже упоминал ранее, класс документа Main будет иметь некоторую часть управления игрой Sprite и UserInterface3D. Вернитесь в класс Main и добавьте еще 3 свойства экземпляра:

Затем зайдите в метод onLoad () и закомментируйте все, что связано с классом Tester, затем добавьте приведенный ниже код.

Это просто добавляет экземпляр UserInterface3D на сцену и прослушивает, когда нажимается кнопка запуска игры. Затем добавьте метод startGame ():

Здесь мы загружаем простой спрайт, представляющий вашу игру. Текст внутри него получает информацию непосредственно из экземпляра UserInterface3D, а также показывает, загружен ли SWF-файл в плагин или в автономный проигрыватель Flash Player. Ему назначается прослушиватель щелчков, поэтому класс основного документа может снова загрузить экземпляр UserInterface3D при щелчке по этому спрайту.

Метод ниже заботится о перезагрузке UserInterface3D:

Поздравляем! Вы успешно завершили проект! Теперь запустите полнофункциональное приложение, чтобы увидеть результат.


Как я уже говорил в своем учебнике по Atoms , Papervision3D — очень простой и мощный инструмент. Поэкспериментируйте с ним, и вы получите всевозможные интересные 3D-эффекты — от простых симуляций до сложных интерфейсов. Теперь у вас есть опыт создания GUI-фреймворка, загруженного эффектами, используя PV3D. Наряду с загрузкой исходного кода, я создал простое приложение для рисования, которое поможет вам в разработке вашего интерфейса. Это идет с короткой запиской о том, как использовать это.

Надеюсь, вам понравилось читать эту статью.

Как всегда, по любым вопросам, предложениям или проблемам, пожалуйста, оставьте примечание в разделе комментариев.

Спасибо за прочтение!