Статьи

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

В этом Tut вы узнаете, как создать законченную структуру 3D-интерфейса, которую вы легко сможете изменить и использовать повторно. Я обещаю, что к тому времени, как вы закончите, вы лучше поймете Papervision3D, изучите несколько эффектов и примените их к PV3D.

У вас также будет хорошее понимание ООП и того, как классы работают вместе в таком среднем проекте, как этот. Мы начнем с самого простого класса и перейдем к более сложному. Всего в проекте работают 17 классов. Кроме того, интерфейс настроен так, что вы можете легко подключить любую игру, которую вы разработали.


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

Откройте FlashDevelop и нажмите «Проект»> «Новый проект»



Выберите Actionscript 3> AS3 Project.

Название проекта можно найти по http://active.tutsplus.com/about/write-a-tutorial/ .

Для определения местоположения щелкните и перейдите в папку, в которую вы хотите сохранить ее.
Оставьте флажок «Создать каталог для проекта» установленным и нажмите «ОК».


Если вы хотите использовать Flash CS3 +, создайте новый файл Flash и установите ширину и высоту 1000×700, установите цвет фона на черный и установите частоту кадров 40. Назовите его interface3D.fla и сохраните его где угодно.


Для FlashDevelop откройте каталог проекта и скопируйте или перетащите soundAssets из исходной загрузки (ссылка вверху страницы) в папку \ bin \. Внутри исходной папки для загрузки находится еще одна папка с именем actionscript. Эта папка содержит все классы Actionscript для проекта. За исключением Millenia.as и CustomLoader.as, остальные классы в этой папке являются законченными версиями того, что вы будете писать. Вы можете сравнивать свою работу с ними каждый раз, когда заканчиваете класс, созданный с нуля, после руководство. Перетащите файлы Millenia.as и CustomLoader.as в папку \ src \, где находится класс Main.as. Эти 2 класса приходят как халява. Я буду обсуждать больше о них позже.

Для Flash скопируйте или перетащите папку soundAssets из исходной загрузки в ту же папку, где находится файл interface3D.fla. Затем перетащите 2 вышеупомянутых класса в ту же папку.

Давайте рассмотрим содержимое папки soundAssets. У нас есть 10 звуковых файлов в формате MP3, которые будут использоваться для звуковых эффектов.



Мы собираемся использовать TweenLite для анимации движения и Papervision для 3D. Оба пакета включены в исходный код загрузки. Для получения дополнительной информации, вы можете посетить их сайты в Papervision и TweenLite .

Для FlashDevelop, скопируйте или перетащите greensock.swc и Papervision3D_2.1.932.swc из исходного кода в папку \ lib \ для этого проекта.

В FlashDevelop нажмите «Просмотр»> «Диспетчер проектов».



Находясь в FlashDevelop, щелкните значок «+» слева от папки lib, чтобы развернуть ее.

Выберите оба файла SWC и щелкните правой кнопкой мыши, выберите «Добавить в библиотеку».


Для Flash скопируйте или перетащите папки \ com \, \ org \ и \ nochump \ из исходной загрузки в ту же папку, что и файл interface3D.fla.


Если вы используете Flash CS3 +, просто следуйте инструкциям. Инструкции для Flash CS3 + продолжаются в шаге 8.

Теперь во FlashDevelop нажмите «Просмотр» и выберите «Диспетчер проектов», как вы делали на шаге 4. После запуска «Диспетчер проектов» перейдите в папку \ src \ и дважды щелкните, чтобы открыть класс Main.as. Этот класс является классом документа для этого проекта и автоматически генерируется для каждого нового проекта. Ниже приведен список обязанностей, которые необходимо учитывать для нашего приложения.

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

Обратите внимание, что для второй ответственности этого класса мы сначала будем использовать класс Tester, а затем заменим его классом UserInterface3D. Тестер будет использоваться для создания и тестирования трехмерных классов по мере их создания, а UserInterface3D объединит их все в одно законченное приложение.

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

Все эти импорта будут использованы ко времени завершения проекта. Что касается переменных экземпляра, давайте начнем с 2, _timer, который будет экземпляром Timer, назначенным со случайной задержкой, для воспроизведения звуковых эффектов, чтобы добавить атмосферу в наш проект, и _customLoader для хранения одного экземпляра класса CustomLoader, который будет использоваться загрузить все звуковые активы.

Добавьте следующие строки кода внутри объявления класса над методом конструктора:


По-прежнему в FlashDevelop, чуть ниже, где в методе init () написано «точка входа», добавьте следующие строки кода:

Для тех из вас, кто не знаком с классом CustomLoader, он в основном используется для загрузки визуальных и звуковых ресурсов. Он основан на шаблоне Singleton, чтобы убедиться, что есть только один экземпляр, который будет содержать все внешние ресурсы для проекта. Мой другой учебник по созданию вступлений с PV3D, связанный здесь , содержит подробную информацию по созданию этого класса.

Его список обязанностей:

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

Чтобы начать использовать класс CustomLoader, мы назначаем _customLoader экземпляр, возвращаемый путем вызова статического метода CustomLoader.getInstance (). Как только экземпляр _customLoader был создан, важно добавить к нему прослушиватель ‘CustomLoader.ALL_LOADS_COMPLETE’. Это сообщит нам, когда все активы были успешно загружены. Чтобы добавить визуальный ресурс, например изображение, в очередь на загрузку, просто вызовите метод addItem () и передайте в качестве параметра URL-адрес. Для звуковых ресурсов вызовите addSound (), а также передайте в качестве параметра URL-адрес.

Как только все ресурсы, которые вы хотите загрузить, были добавлены в очередь, вызовите метод startLoading (). Имена для каждого актива звука / изображения генерируются автоматически, получая его краткое имя. Например: если вы загрузите «soundAssets / menuCollapse.mp3», имя для доступа к этому звуковому ресурсу будет «menuCollapse». Чтобы получить список всех имен всех ресурсов (изображений и звуков), просто вызовите _customLoader.names, например, trace (_customLoader.names), и все имена будут напечатаны в виде массива имен. Чтобы получить доступ к изображениям, вызовите метод _customLoader.getItem () и просто передайте короткое имя в строковом формате. Для звуков вызовите _customLoader.getSound () и передайте короткое имя также в строковом формате. Нам нужно будет только загрузить звуковые ресурсы для этого проекта, так как вся графика будет сгенерирована Papervision3D.


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

Теперь, когда вы запускаете проект, вы должны услышать случайный звук. Запустите его еще несколько раз, и вы, вероятно, услышите другой звук каждый раз.

Для Flash создайте новый класс с именем «Main», где вы сохранили ваш interface3D.fla, и используйте его в качестве класса Document. Импорт обычно генерируется FlashDevelop автоматически, но, поскольку вы используете Flash для создания своих классов, просто добавьте их все сейчас, и вы увидите, для чего они будут использоваться позже. Скопируйте код ниже и замените весь код внутри нового класса:

Теперь запустите приложение, нажав CTRL + ENTER.

Большой! Теперь мы знаем, что CustomLoader работает! Давайте двигаться дальше.


Замените содержимое метода onLoad () следующим кодом:

Здесь мы присваиваем локальной переменной ‘sound’ экземпляр background2.mp3 и воспроизводим его 100 раз. Затем вызывается метод createRandomNoise (). Добавьте следующий код ниже метода onLoad ():

Добавьте метод onTimerComplete () ниже метода createRandomNoise ().

Для завершения класса добавьте статический метод getRandomInRange (). Этот полезный метод объявлен статическим, чтобы максимизировать его доступность. Он просто генерирует случайное число между $ min и $ max и возвращает его:

  • округляется, если третий параметр оставлен по умолчанию,
  • как число с плавающей запятой, если для третьего параметра установлено значение false.

Добавьте следующие строки кода ниже метода onTimerComplete ():

Все, что делает метод createRandomNoise () — назначает новый экземпляр Timer _timer со случайным интервалом от 5 до 20 секунд. Затем слушатель onTimerComplete запускается каждый раз, когда завершается таймер, и именно здесь воспроизводится звук «randomEcho», и, как вы можете видеть, генерируемый звук имеет переменную громкость от 0 до 0,7. Затем он снова вызывает метод createRandomNoise (), чтобы запустить новый таймер. Это создает какой-то случайный звуковой цикл с переменным интервалом. Идите вперед и запустите тест, если все работает. Если все прошло хорошо, вы должны услышать звуковые эффекты в фоновом режиме при запуске программы.

Сохраните свою работу и давайте перейдем к созданию 3D-объектов.


Если вы используете Flash CS3 +, опять же, просто следуйте инструкциям. Инструкции для Flash CS3 + будут продолжены на шаге 13.

Как упоминалось ранее, этот класс будет использоваться для тестирования 3D-объектов. Этот класс будет унаследован от BasicView, что делает быстрый 3D-шаблон готовым к использованию. В FlashDevelop нажмите «Просмотр»> «Диспетчер проектов», щелкните правой кнопкой мыши папку \ src \ и выберите «Добавить»> «Новый класс».


Откроется окно New Actionscript Class. В качестве имени введите «Tester», для базового класса нажмите «Обзор» и введите «org.papervision3d.view.BasicView». Нажмите «ОК», чтобы закончить.


Это простой класс. Его обязанности заключаются в следующем:

  1. Добавьте простую трехмерную перспективу.
  2. Создайте простой 3D-объект в качестве прототипа в качестве отправной точки для создания пользовательских классов DisplayObject3D.
  3. Протестируйте каждый пользовательский DisplayObject3D, созданный при их создании.

Добавьте следующий импорт в скобки пакета перед объявлением класса:


Теперь добавьте следующие частные переменные экземпляра в объявление Class:

Эти 5 переменных будут использоваться для перемещения камеры по орбите. Объекты, добавленные в сцену, не будут двигаться, но будут выглядеть так, поскольку камера будет перемещаться вокруг них. Мы добавим другие переменные при разработке соответствующих им классов DisplayObject3D. Когда мы доберемся до UserInterface3D, у нас будут объекты вращаться и вместо этого держать камеру в неподвижном положении.


Конструктор вызовет 2 метода для запуска, во-первых, метод init (), который будет обрабатывать общую инициализацию, и, во-вторых, startRendering (), который запустит движок 3D-визуализации Papervision. Добавьте следующие строки кода в метод конструктора:


Этот метод позаботится об инициализации трехмерных объектов, которые мы собираемся создать. А пока давайте добавим простой DisplayObject3D в сцену в качестве разминки. Добавьте следующие строки кода ниже метода «Конструктор тестера»:

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

Во-первых, мы создаем VectorShape3D, этот класс является 3D-версией Papervision для 3D-графики. Чтобы сделать этот трехмерный графический актив, нам нужен экземпляр VectorShapeMaterial для использования в качестве его материала. После создания экземпляра VectorShape3D мы можем получить доступ к его свойству Graphics3D для рисования.

Использование Graphics3D очень похоже на использование встроенного в Flash класса Graphics. Здесь мы назначаем локальную переменную с именем ‘material’ типа VectorShapeMaterial новому экземпляру. Затем создается другая локальная переменная с именем ‘vs3D’ типа VectorShape3D, присваивающая ‘material’ в качестве параметра. Чтобы начать рисование, локальной переменной с именем «g» назначается свойство Graphics3D в VectorShape3D. Цвет устанавливается путем вызова метода Graphics3D beginFill () и передачи цвета 0xFF0000 (красный). Кроме того, вы можете передать значение от 0 до 1 в качестве второго параметра для установки свойства alpha. Мы устанавливаем свойство линии Graphics3D, вызывая его метод lineStyle () и передавая 2 параметра, чтобы установить его свойства толщины и цвета соответственно. Здесь мы устанавливаем толщину 1, а цвет — 0x0000FF (синий). Затем рисование начинается с вызова метода MoveTo в Graphics3D и передачи начальных позиций x и y. Здесь мы начинаем в левом верхнем углу -199 единиц слева от центра оси ‘x’ и 106 единиц вверх по оси y. Вызов метода lineTo () Graphics3D затем повторяется 4 раза, чтобы нарисовать квадрат VectorShape3D. Форма рисуется путем создания линии от начальной точки (-199,106), идущей вниз (-199, -106), затем вправо (199, -106), а затем вверх (199,106) и, наконец, заканчивая квадрат, назад до (-199,106).

Чтобы применить альфа-прозрачность 0,6 к объекту VectorShape3D, мы назначаем локальное свойство с именем vLayer типа ViewportLayer, ViewportLayer экземпляра VectorShape3D. Мы делаем это, вызывая метод Viewport.getChildLayer () и передавая экземпляр VectorShape3D, назначенный для vs3D, этот параметр принимает объекты DisplayObject3D. После назначения вы можете применять эффекты для 3D-ресурса точно так же, как и к обычному экранному объекту.

Следующее, что мы делаем, это добавляем 3D текст. Здесь мы сначала будем использовать импортированный класс Millenia.as. Этот класс представляет собой 3D-шрифт, созданный с помощью программного обеспечения Mathuie Badimon «Make the typography file» версии 2.0 Вы можете получить больше информации об этом здесь . Чтобы создать трехмерный векторный текст, нам нужно создать 4 свойства и передать их в качестве параметров при создании трехмерного текста:

  1. 1-й текст, который он напишет, находится в строке String. Здесь мы передаем ему переменную nameString.
  2. Далее letterMaterial типа LetterMaterial. При создании экземпляра этого класса мы передаем цвет 0x00FF00 (зеленый). Если оставить его в покое, параметры по умолчанию будут розовыми для цвета и 1 для альфы (полная непрозрачность).
  3. Третьей переменной font3D типа Font3D назначается экземпляр класса Millenia.as.
  4. 4-й и необязательный параметр — это параметр имени, используемый в качестве имени для экземпляра Text3D. Это тоже в формате String.

Здесь мы создаем новый Text3D и передаем ему nameString для использования в качестве текста, font3D для его шрифта, letterMaterial для его материала и снова nameString для его последнего и необязательного параметра, его свойства name. Все, что нам нужно сделать сейчас, это расположить его, установить его свойство align и добавить его в сцену. Так как мы используем шрифт Millenia.as для этого проекта, мы установим свойство выравнивания Text3D в ‘left’, его позиция ‘x’ установлена ​​в 650, чтобы центрировать его по оси ‘x’, позиция ‘y’ назначена 10 чтобы центрировать его ось ‘y’, наконец, позиция ‘z’ установлена ​​в -25, чтобы она появилась перед VectorShape3D.

Чтобы применить альфа-прозрачность, мы будем использовать тот же метод, который мы использовали для VectorShape3D, который мы создали ранее. Локальной переменной с именем tLayer типа ViewportLayer назначается ViewportLayer для text3D. Опять же, это делается путем вызова метода экземпляра Viewport ‘getChildLayer’ и передачи text3D в качестве параметра. Значение альфа 0 затем устанавливается для tLayer. Это единственный способ применить фильтры и эффекты ко всему, что наследуется от DisplayObject3D. Как вы увидите позже, когда мы рассмотрим эффекты более широко.

Здесь мы создаем новый Text3D и передаем ему nameString для использования в качестве текста, font3D для его шрифта, letterMaterial для его материала и снова nameString для его последнего и необязательного параметра, его свойства name. Все, что нам нужно сделать сейчас, это расположить его, установить его свойство align и добавить его в сцену. Так как мы используем шрифт Millenia.as для этого проекта, мы установим свойство выравнивания Text3D в ‘left’, его позиция ‘x’ установлена ​​в 650, чтобы центрировать его по оси ‘x’, позиция ‘y’ назначена 10 чтобы центрировать его ось ‘y’, наконец, позиция ‘z’ установлена ​​в -25, чтобы она появилась перед VectorShape3D. Чтобы применить альфа-прозрачность, мы будем использовать тот же метод, который мы использовали для VectorShape3D, который мы создали ранее. Локальной переменной с именем tLayer типа ViewportLayer назначается ViewportLayer для text3D. Опять же, это делается путем вызова метода экземпляра Viewport ‘getChildLayer’ и передачи text3D в качестве параметра. Значение альфа 0 затем устанавливается для tLayer. Это единственный способ применить фильтры и эффекты ко всему, что наследуется от DisplayObject3D. Как вы увидите позже, когда мы рассмотрим эффекты более широко.

Чтобы все было организовано, мы будем использовать пустой DisplayObject3D для размещения VectorShape3D и Text3D, а затем добавим это в сцену. Создается локальная переменная с именем do3D типа DisplayObject3D, добавляет в нее vs3D и text3D, а затем добавляет ее в сцену.

Вернитесь к своему классу Main.as и добавьте приведенный ниже код в метод onLoad () после вызова метода createRandomNoise ():

Теперь запустите его, чтобы просмотреть продукт. Это должно выглядеть как вырез ниже со звуковыми эффектами, играющими на заднем плане. Если вы используете Flash, просто добавьте код выше в Main.as и следуйте до конца этого шага.


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

Этот метод взят из суперкласса BasicView AbstractView. Он срабатывает при каждом событии enterFrame после вызова метода startRendering (), как мы это делали внутри метода init ().

Теперь, когда вы запустите тест, вы увидите, что камера теперь вращается вокруг вашего DisplayObject3D. Может показаться, что объект движется, но на самом деле это камера, которая вращается вокруг центра сцены. В этом методе основной функцией является метод Camera.orbit (). Чтобы использовать этот метод, xDist & yDist назначаются расстояния mouseX & mouseY от центра сцены, исходя из ширины и высоты сцены. Экземплярная переменная _camPitch типа Number используется в качестве значения для вращения камеры по оси ‘y (перемещение влево или вправо). Это рассчитывается сначала умножением yDist на _rotX, а затем вычитанием текущего значения _camPitch plus 90. При сложении 90 камера настраивается таким образом, что, когда мышь находится в центре, камера также смотрит прямо в центр сцены. Затем _easOut умножается на общее значение, чтобы применить замедление к движению камеры. Та же концепция применима к _camYaw, эффект которой применяется к оси ‘камеры’ камеры (перемещение вверх или вниз). Мы добавляем 270, чтобы центрировать камеру, когда мышь находится в центре сцены. Затем две переменные передаются в метод Camera.orbit () для перемещения камеры. Наконец, super.onRenderTick () вызывается в конце метода, чтобы суперклассы могли визуализировать трехмерную сцену.

Хорошо, запустите еще один тест и увидите, что происходит движение 3D!

Вау! Ты это видел?! Я не говорю о трехмерной перспективе. Когда вы перемещаете мышь влево от сцены, вы замечаете, как Text3D переместился в заднюю часть VectorShape3D? У вас проблема с сортировкой «Z». Не волнуйтесь, у нас есть простое решение, которое мы добавим к классу UIComponent3D, который мы создадим дальше. Сохраните свою работу, прежде чем перейти к следующему шагу.

Если вы используете Flash, примените упомянутые ранее изменения к классу «Основной документ» и продолжайте здесь. Создайте новый класс с именем Tester.as, сохраните его в той же папке, где у вас есть файл interface3D.fla. Скопируйте приведенный ниже код, сохраните его снова и запустите.

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


Этот класс должен упростить добавление нарисованного VectorShape3D с произвольно видимым text3d в сцену. Он также будет отвечать за сортировку «z». Это будет частью решения, которое мы обсудим позже. Он будет добавлять, удалять и отправлять InteractiveScen3DEvents, рисовать трехмерные векторы и вычислять их размеры. Этот класс будет служить в качестве суперкласса для всех различных визуальных ресурсов (включая кнопки), используемых в этом проекте. Вот список его обязанностей:

  1. обеспечить свойства ширины и высоты, переведенные в систему измерения единиц измерения PV3D.
  2. нарисовать собственный вектор vetershape3d и получить доступ к его ViewportLayer для применения эффектов.
  3. добавить text3D, также получить доступ к его ViewportLayer для применения эффектов.
  4. организовать сортировку z.
  5. добавьте прослушиватели, удалите прослушиватели и отправьте InteractiveScene3DEvents.

Для FlashDevelop создайте новый класс, назовите его UIComponent3D и сделайте так, чтобы он расширял DisplayObject3D. Смотрите Шаг 10 для повышения квалификации.

Для Flash создайте класс внутри папки, которую вы использовали для interface3D.fla.

Выделите весь код внутри класса и замените его следующими строками:

После объявления пакета идет импорт всех необходимых классов. Затем идет объявление класса. Ниже вы видите все защищенные переменные, необходимые для его функциональности. Комментарии перечислены справа от каждой переменной для описания использования. Затем приходит конструктор. Требуются первые 3 параметра, за которыми следует необязательный 4-й параметр. Важно иметь имя для каждого DisplayObject3D для справки. Параметр $ viewport необходим для доступа к ViewportLayer Text3D и VectorShape3D, к которым будут применены эффекты. Параметр координат представляет собой массив Number2D, используемый для рисования. 4-й параметр позволяет показать или скрыть 3D-текст.

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


После создания экземпляра UIComponent3D мы можем настроить свойства VectorShape3D перед рисованием. Добавьте следующие строки кода после конструктора:

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


После того, как мы настроили визуальные свойства, мы можем инициализировать экземпляр UIComponent3D извне. Пример покажет, почему у нас есть этот набор в качестве открытых методов. Здесь setDimensions () вызывается для установки его ширины и высоты. Затем вызывается метод createInterface () для рисования VectorShape3D и, наконец, вызывается createText () для создания Text3D. Добавьте следующий метод выше методов получения:


Нам нужно получить эти свойства для создания интерактивной плоскости позже, когда мы расширим это для нашего класса Button3D. Как вы знаете, объекты Papervision DisplayObject не имеют свойств width и height, поэтому мы добавляем их в качестве пользовательских свойств экземпляра, унаследованных всеми подклассы. Для ширины мы используем простую математику и добавляем самую дальнюю позицию «x» слева от центра, а самую дальнюю позицию «x» — справа. То же самое относится и к высоте. Добавьте код после метода init ():

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


Этот метод вызывается следующим внутри метода init (). Он заботится о добавлении трехмерной графики в UIComponent3D и назначает свой ViewportLayer _interfaceLayer для применения эффектов позже. Помните метод addSimpleDO3D () в классе Tester. Кроме того, теперь он использует массив координат Number2D для рисования. Добавьте следующие строки кода ниже setDimensions ():

Внутри метода есть вызов метода setLayerIndex (), который является частью нашей проблемы с сортировкой z. Он назначает переданный в ViewportLayer параметр layerIndex переданному параметру index. Добавьте его ниже конца метода createInterface ().


Это также было частью метода addSimpleDO3D (), мы просто разделили его для большего контроля и для простоты. Добавьте код над методом setLayerIndex ():

Метод setLayerIndex () вызывается снова, на этот раз передается в ViewportLayer Text3D, и ему присваивается значение _layerIndex + 1. При этом Text3D всегда рисуется перед VectorShape3D. Также обратите внимание, как мы проверяем, что для _showText установлено значение true, по умолчанию это значение равно false как последний параметр метода Constructor.


Для Papervision это событие, которое вы хотите услышать для интерактивности. Добавьте следующие коды ниже метода setLayerIndex ():

Первые 2 упрощают добавление и удаление событий MouseOver, MouseOut и MouseClick. Последние 3 заботятся об их отправке. Все это помогает расширяющемуся подклассу — Button3D. Я решил поместить эти методы в UIComponent3D, чтобы сосредоточить Button3D на своих других обязанностях.


Добавьте методы ниже, чтобы позволить другим классам применять эффекты для каждого UIComponent3D. Это будет использоваться DistortionEffect3D, который вы создадите позже.


Нам придется вручную корректировать положение для каждого Text3D, когда мы создадим пару классов-потомков, расширяющих Button3D. Добавьте код ниже после метода get textLayer ():

Это завершает наш класс UIComponent3D! Сохраните его, прежде чем перейти к следующему шагу.


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

Помните, как мы настраивали конструктор UIComponent3D? У нас есть 3 обязательных параметра и 1 необязательный, который по умолчанию равен false. Первый параметр используется как имя и текст. Вторым является свойство Viewport3D BasicView для доступа к ViewportLayers для UIComponent3D. Третий — это массив Number2D, который используется для рисования VectorShape3D. И наконец, необязательный параметр $ showText, который здесь мы устанавливаем в true. Следующее, что нам нужно после создания экземпляра UIComponent3D, — это вызвать его метод init (). Затем мы позиционируем его Text3D и добавляем его в сцену. Визуальные свойства — это то, что мы устанавливаем по умолчанию. Чтобы изменить цвет и прозрачность для заливки и стиля линии, просто назначьте их перед вызовом метода init (). Мы применим их позже, когда будем создавать более сложные DisplayObject3D, такие как MainMenu3D. Text3D не делаетУ нас нет никакого способа изменить цвета, так как нам здесь это не нужно, но вы всегда можете добавить для этого другой необязательный параметр для конструктора UIComponent3D. Объявите _uic как свойство экземпляра типа UIComponent3D и затем запустите программу.

Ваш результат должен быть похож на изображение ниже.


Ok. Оно работает.Но у нас все еще есть проблема сортировки по z, даже когда мы уже управляем layerIndex для наших VectorShape3D и Text3D. Чтобы сортировка layerIndex ‘z’ вступила в силу, нам нужно изменить режим сортировки containerSprite области просмотра на сортировку по индексу. Зайдите в метод тестера init () и добавьте приведенный ниже код, прежде чем что-либо еще.

Убедитесь, что следующий импорт включен в пакет Tester, прежде чем снова запускать приложение.

Хорошо!Это решает проблему сортировки «z». Опять же, если у вас есть ошибки, проверьте свой код по завершенным классам, включенным в исходную загрузку. Если все прошло хорошо, давайте начнем создавать класс Button3D.


Для Button3D вместо того, чтобы просто отправлять события мыши, а затем расширять его для добавления эффектов, мы сделаем все это за один раз. Кроме того, это одна из причин, по которой мы добавили слушателей в суперкласс Button3D — UIComponent3D. Он наследует от UIComponent3D, затем добавляет свою собственную функциональность. Вот список его обязанностей:

  1. играть звуковые эффекты для мыши и мыши.
  2. добавить интерактивную плоскость, которая будет вызывать события мыши.
  3. применять эффекты для наведения мыши, мыши и щелчка мыши.
  4. обеспечить внешнее управление для добавления и удаления слушателей событий мыши.
  5. обеспечить внешнее управление для удаления обработчиков щелчков мыши, используемых при создании кнопок, которые слушают только при наведении курсора мыши и при отсутствии мыши для прокрутки Text3D, как вы видели в меню «О программе».

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

Как обычно, требуемый импорт находится в верхней части страницы как часть пакета. Внутри объявления класса первые 2 свойства объявлены как открытые статические константы, так как оба будут использоваться внешними классами и классами-потомками. Они для позиционирования «Z» для кнопки. Остальные 5 являются переменными экземпляра, доступными для подклассов. Смотрите комментарии для их использования. Метод конструктора принимает те же параметры, что и суперкласс, на этот раз установка третьего параметра также необязательна. 4-й параметр также изменен, чтобы показать текст по умолчанию.


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

Первое, что он делает, это проверяет, является ли значение $ координаты нулевым, если это так, он назначает свой собственный набор. Таким образом, всякий раз, когда экземпляр этого класса создается с третьим параметром, установленным в нуль, он будет иметь набор координат по умолчанию для рисования. (Я включил в учебник простой инструмент рисования, который можно использовать для генерации этих координат.)

Затем выполняется вызов метода super (), передавая присвоенные значения, которые обрабатываются UIComponent3D. Затем к экземпляру CustomLoader осуществляется доступ к звуковым эффектам, используемым для событий мыши. Громкость звуков, которые мы используем, немного громкая, поэтому мы компенсировали это классом SoundTransform.


Помимо рисования VectorShape3D, мы также хотим добавить плоскость, которая будет прослушивать события мыши здесь, в Button3D. Мы можем сделать это, переопределив метод createInterface (), унаследованный от UIComponent3D, и применить к нему новые функциональные возможности. Добавьте код ниже после конструктора:

Это лучший пример, чтобы показать эффективность ООП. Переопределяя унаследованный метод, а затем просто добавляя его, мы избегаем дублирования кода. Все, что мы здесь сделали, это вызвали super.createInterface (), передав параметр, чтобы UIComponent3D сделал свое дело, а затем вызвав addInteractivePlane (), чтобы Button3D добавила плоскость для интерактивности. Добавьте код ниже после метода createInterface ():

Метод прост. Он назначает новую плоскость с цветом 0 (черный) и альфа 0, чтобы сделать ее полностью прозрачной. Здесь мы используем свойства _width и _height, унаследованные от UIComponent3D. Чтобы создать плоскость, мы просто создаем экземпляр, передав 3 параметра: цветной материал, который мы установили на черный с полной прозрачностью, а затем _width и _height. После создания он помещается в ту же позицию «x», что и унаследованный _interfaceGraphic VectorShape3D. Затем Button3D добавляет его как дочерний элемент и вызывает метод activ (). Здесь вызывается метод activ (), чтобы после создания экземпляра Button3D он автоматически становился интерактивным. Я подробнее расскажу о методах activ () и deActivate (), когда мы их доберемся.


Моя любимая часть, создание эффектов! Итак, давайте рассмотрим эффект, которого мы хотим достичь. Чтобы навести курсор мыши, мы хотим, чтобы кнопка приблизилась к камере, воспроизвела звук, на секунду загорелась, а затем снова вернулась в нормальное состояние. Для мыши, мы просто хотим, чтобы кнопка вернулась в исходное положение. Для щелчка мышью мы хотим, чтобы кнопка также вернулась в исходное положение, моргнула 3 раза, а затем отправила событие щелчка кнопки, чтобы меню, содержащее их, не закрывалось до окончания 3 миганий. Давайте начнем с эффекта наведения мыши. Добавьте следующий код ниже метода addInteractivePlane ():

Во-первых, мы воспроизводим звук, назначенный для мыши. Затем мы перемещаем кнопку ‘z’ на 50 единиц ближе к камере. Помните, вы присваивали им свойства ViewportLayer для VectorShape3D и Text3D, когда мы создавали UIComponent3D? Мы используем TweenMax, потому что он имеет дополнительную возможность применения эффектов размытия и свечения, не говоря уже о других, которых нет у TweenLite. Здесь мы немедленно назначаем массив фильтров как _interfaceLayer, так и _textLayer. Это так же просто, как назначить фильтры обычному классу Sprite, так как по сути ViewportLayer является Sprite. TweenMax используется для исчезновения эффектов. Затем выполняется вызов метода onObjectOver () UIComponent3D, передавая то же событие InteractiveScene3DEvent, которое вызвало этот.

Затем, для мыши, добавьте приведенный ниже код после метода onObjectOver ():

Все, что это делает, это вызывает метод onObjectOut () UIComponent3D и помещает кнопку обратно в исходное положение.

Теперь для эффекта щелчка мыши. Добавьте следующий метод под методом onObjectOut ():

Когда нажимается экземпляр Button3D, первое, что он делает, — это воспроизводит звук. Затем он возвращается в исходное положение «z». Затем вызываются два метода — flashText () и deActivate (). Мы используем InteractiveScene3D.OBJECT_RELEASE, чтобы сообщить MainMenu3D, удерживающему этот Button3D, чтобы он мог отключить все остальные кнопки после того, как выбор уже сделан. Добавьте 2 вспомогательных метода под методом onObjectClick ():

Итак, есть еще один вспомогательный метод, помогающий вспомогательному методу flashText (). Эй, все, что нужно для достижения эффекта, верно ?! знак равно
Когда вызывается flashText (), он создает таймер с задержкой 15 миллисекунд, которая повторяется 9 раз. Затем метод blink () назначается в качестве обратного вызова для каждого события TIMER, dispatchClick () назначается в качестве обратного вызова для события TIMER_COMPLETE. каждый раз, когда вызывается метод blink (), видимость _text3D переключается. Это происходит 9 раз, и это выглядит так, как будто текст моргнул очень быстро 3 раза. После завершения таймера blink () вызывается еще раз, чтобы снова сделать _text3D видимым, и отправляется событие onObjectClick.


Добавьте следующие строки кода:

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


Зайдите в демонстрационное приложение еще раз и поиграйте с меню About. Обратите внимание, что скроллерам не нужно слушать щелчки мыши. Для этого нам нужно будет добавить функциональность для удаления слушателя щелчка мыши, автоматически добавляемого по умолчанию. Добавьте 2 метода внизу класса:

Метод set set noClick () просто назначает передаваемый ему логический параметр. Чтобы удалить прослушиватель щелчков, просто вызовите этот метод и передайте значение true перед вызовом метода init () кнопки. Button3D переопределяет метод addMouseListeners () и проверяет, имеет ли свойство _noClick значение true, если это так, он прекращает прослушивание событий щелчка.


Вернитесь к Tester.as и закомментируйте вызов метода addCustomDO3D () внутри метода init (). Затем добавьте вызов метода addButton () под ним. Затем добавьте 2 метода, перечисленных ниже, после метода init ():

Сначала он назначает локальную переменную с именем «b» в качестве экземпляра Button3D и передает имя и текст «кнопки 0» и область просмотра. Помните, что последние 2 параметра являются необязательными. Теперь запустите это. Вы должны увидеть что-то вроде выреза ниже:


К сожалению!Нет взаимодействия с мышью ?! Для прослушивания событий мыши, во-первых, нам нужно сделать интерактивный видовой экран. Вернитесь в метод init () Tester и добавьте код под присваиванием sortMode:

Это оно!Запустите его снова и посмотрите, как он реагирует на мышь. Метод onButtonClick () сообщает нам, что кнопка нажата с помощью трассировки, а затем мы вызываем Button3D.activate () для кнопки, чтобы она снова прослушивала события мыши. Помните, у нас есть этот набор, чтобы отключить себя, как только кнопка нажата. Кроме того, вы можете изменить скорость миганий, если считаете, что она немного быстрая — см. Шаг 27. Но как только эффекты добавлены, вам, возможно, придется заново отрегулировать их.

Давайте сделаем еще одну кнопку, на этот раз, давайте немного настроим ее, так как последняя имела все свойства по умолчанию. Измените код внутри addButton на то, что мы имеем ниже:

Чтобы мы знали, что слушатели событий mouse over и mouse out работают, добавьте приведенный ниже код после метода onButtonClick () перед запуском другого теста:

Вот снимок нашего нового Button3D с назначенными нами пользовательскими свойствами.


И это завершает наш класс Button3D. Теперь расслабься, отдохни и возвращайся, когда будешь готов к большему


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

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

Создайте новый класс и назовите его MainMenu3D. Пусть он расширяет DisplayObject3D. Когда файл класса открыт, просто скопируйте и вставьте приведенный ниже код, заменив содержимое класса.

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


Конструктор принимает 2 обязательных параметра: $ name и $ viewport. super () вызывается для назначения $ name для экземпляра DisplayObject3D. И $ viewport сохраняется для справки позже. Добавьте код ниже внутри метода конструктора:


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

Первый метод createFrame () просто добавляет 2 границы как дочерние. Мы используем UIComponent3D, так как все, что им нужно, это визуальные компоненты. Добавьте следующий код ниже метода init ():

Метод addButtons () заботится о добавлении 4 кнопок. Добавьте код ниже, следующий:

Здесь _buttonArray назначается новый массив для хранения ссылок на 4 кнопки. По мере итерации _buttonTitles слушатели для OBJECT_CLICK и OBJECT_RELEASE добавляются для каждой созданной кнопки. затем они позиционируются на оси ‘y’ на основе _buttonPosY для текущей итерации. Помните, как мы настраивали метод onObjectClick () для Button3D, 1-й позаботится о дополнительных анимационных эффектах для кнопки, а другой распространяется до MainMenu3D. Вы увидите его использование, когда мы перейдем к обработчикам событий позже.

Наконец, метод setMenuEffect (). Добавьте код ниже:

Здесь мы добавим эффект искажения. А пока оставьте это, пока мы не создадим собственный класс DistortionEffect3D. Мы сделаем это дальше, как только закончим MainMenu3D.


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

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

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

Этот метод вызывает prepareIntro (), чтобы получить все на своем месте перед запуском анимации. Локальной переменной звука типа Sound присваивается ссылка на звуковой эффект с именем ‘menuExpand’, сохраненный в экземпляре CustomLoader. Затем TweenMax используется для постепенного исчезновения альфа-свойства 2 границ. Эта анимация имеет длительность 0,4 секунды и коэффициент задержки 0,5 секунды. Звук вызывается для воспроизведения при запуске, и анимация настроена так, чтобы не перезаписываться. Еще один вызов TweenMax назначен для фактического перемещения 2 границ, на этот раз с задержкой 0,75 секунды. .25 секунд после начала постепенного изменения, 2 границы анимируются для открытия. 2 границы открываются через 0,5 секунды, а когда они заканчиваются, вызывает метод initializeButtons ().

Добавьте код ниже:

Вот как 4 кнопки активируются и затем последовательно добавляются в меню. Он рассчитывает назад от количества кнопок, задержанных на 0,07 секунды. На каждой итерации вызывается showButtons (), передавая значение _buttonArray для текущей итерации. Ниже приведен последний метод, который завершает вводную анимацию:

Как только это вызвано, кнопка, переданная как параметр, обрабатывается. Сначала она показывает кнопку, а затем запускает ее метод onObjectOver () для имитации события мыши. Сразу после этого она помещает кнопку в положение мыши по умолчанию.


Внутри MainMenu3D кнопки будут обрабатываться по их названию, чтобы идентифицировать, какая кнопка была нажата, и отправлять соответствующее событие, которое нужно вызвать. Метод onButtonClick () отправит событие в MainMenu3D, содержащий родительский элемент, либо UserInterface3D, либо класс Tester, который мы используем в данный момент. Добавьте код ниже:

Остальная анимация для кнопки выполняется самой кнопкой. Помните, мы установили этот метод так, чтобы он вызывался методом onObjectClick () каждой кнопки. Этот метод заботится обо всех эффектах анимации кнопок перед отправкой этого события вверх. После отправки соответствующего события меню информируется о выходе. Затем добавьте приведенный ниже код для метода onButtonRelease ():

Это самый простой метод для MainMenu3D, его единственная цель — убедиться, что при нажатии кнопки пользователь, независимо от того, как быстро он пытается, не сможет нажать другую кнопку и, возможно, вызвать что-то нежелательное. Вернитесь к методу onObjectClick () Button3D, чтобы увидеть, как это происходит.


Как только пользователь решит, что делать, либо отредактируйте настройки, играйте в игру, что угодно, Mainmenu3D начнет выходить и сообщит Tester или UserInterface3D, когда это будет сделано. Обратите внимание, что этот метод объявлен как public, соответствующий его аналогу startIntro (). UserInterface3D не нужно будет вызывать этот метод, поскольку он обрабатывается внутри. Добавьте код ниже:

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

Этот метод заставляет кнопки мигать одна за другой, а затем прятаться по порядку до того, как 2 границы анимации закрываются. Сначала он имитирует эффект мыши. Применяется еще один метод delayedCall (), чтобы кнопка оставалась достаточно длинной, чтобы завершить действие над кнопкой до ее удаления из видимости. После этого он проверяет, является ли обрабатываемая кнопка последней кнопкой в ​​списке кнопок, и если это так, вызывает метод closeNav (). Добавьте следующие 2 метода:

Как только все кнопки станут невидимыми, 2 границы начнут закрываться. Первые 2 вызова TweenMax заботятся о затухании верхней и нижней границ. Затухание занимает 0,2 секунды с задержкой 0,4 секунды. Конец замирания отправляет событие EXIT_COMPLETE. Для второго набора вызовов TweenMax границы анимируются внутрь закрывающим образом. Это займет 0,5 секунды, использует Expo.easeInOut для простоты и не имеет никакой задержки. Этот вызов также воспроизводит звук menuCollapse для звукового эффекта закрытия. И мы закончили с MainMenu3D! Хорошо, сохраните и будьте готовы к тестированию.


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

Здесь создается экземпляр MainMenu3D с передачей имени ‘menu’ для имени и окна просмотра для его свойства _viewport. Затем прослушиватели назначаются для всех событий, которые отправляет экземпляр MainMenu3D. После добавления его в сцену нам нужно вызвать открытый метод MainMenu3D startIntro () для его загрузки. Давайте добавим соответствующие методы для слушателей перед тестированием. Добавьте код ниже после метода addMainMenu ():

Теперь запустите приложение.Нажмите здесь, чтобы увидеть результат:

После нажатия любой из 4 кнопок экземпляр MainMenu3D отправляет событие и завершается. Вы должны увидеть распечатки того, что сработала кнопка. Здесь мы просто загружаем меню снова, когда получено событие MainMenu3D.EXIT_COMPLETE. Опять же, кнопки могут мигать немного быстро, чтобы их заметили все, но они должны замедлиться, как только мы начнем добавлять эффекты. Поиграйте с ним немного, чтобы лучше с ним познакомиться. Мы собираемся расширить этот класс для подменю AboutMenu3D и SettingsMenu3D позже. Теперь давайте поработаем над DistortionEffect3D, прежде чем перейти к более высоким основаниям.


Спасибо за чтение до этого момента! Присоединяйтесь ко мне снова для второй и заключительной части, где мы закончим наш интерфейс.