В этом Tut вы узнаете, как создать законченную структуру 3D-интерфейса, которую вы легко сможете изменить и использовать повторно. Я обещаю, что к тому времени, как вы закончите, вы лучше поймете Papervision3D, изучите несколько эффектов и примените их к PV3D.
У вас также будет хорошее понимание ООП и того, как классы работают вместе в таком среднем проекте, как этот. Мы начнем с самого простого класса и перейдем к более сложному. Всего в проекте работают 17 классов. Кроме того, интерфейс настроен так, что вы можете легко подключить любую игру, которую вы разработали.
Также доступно в этой серии:
- Создайте стильный 3D-интерфейс с Papervision3D: структура
- Создайте стильный 3D-интерфейс с Papervision3D: эффекты и подменю
Шаг 1: Создайте новый проект
Откройте FlashDevelop и нажмите «Проект»> «Новый проект»
Шаг 2: настройка
Выберите Actionscript 3> AS3 Project.
Название проекта можно найти по http://active.tutsplus.com/about/write-a-tutorial/
.
Для определения местоположения щелкните и перейдите в папку, в которую вы хотите сохранить ее.
Оставьте флажок «Создать каталог для проекта» установленным и нажмите «ОК».
Если вы хотите использовать Flash CS3 +, создайте новый файл Flash и установите ширину и высоту 1000×700, установите цвет фона на черный и установите частоту кадров 40. Назовите его interface3D.fla
и сохраните его где угодно.
Шаг 3: Подготовка активов для использования
Для 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, которые будут использоваться для звуковых эффектов.
Шаг 4: Установите TweenLite и Papervision3D
Мы собираемся использовать TweenLite для анимации движения и Papervision для 3D. Оба пакета включены в исходный код загрузки. Для получения дополнительной информации, вы можете посетить их сайты в Papervision и TweenLite .
Для FlashDevelop, скопируйте или перетащите greensock.swc и Papervision3D_2.1.932.swc из исходного кода в папку \ lib \ для этого проекта.
В FlashDevelop нажмите «Просмотр»> «Диспетчер проектов».
Шаг 5: Внешние библиотеки
Находясь в FlashDevelop, щелкните значок «+» слева от папки lib, чтобы развернуть ее.
Выберите оба файла SWC и щелкните правой кнопкой мыши, выберите «Добавить в библиотеку».
Для Flash скопируйте или перетащите папки \ com \, \ org \ и \ nochump \ из исходной загрузки в ту же папку, что и файл interface3D.fla.
Шаг 6: Настройка класса документа
Если вы используете Flash CS3 +, просто следуйте инструкциям. Инструкции для Flash CS3 + продолжаются в шаге 8.
Теперь во FlashDevelop нажмите «Просмотр» и выберите «Диспетчер проектов», как вы делали на шаге 4. После запуска «Диспетчер проектов» перейдите в папку \ src \ и дважды щелкните, чтобы открыть класс Main.as. Этот класс является классом документа для этого проекта и автоматически генерируется для каждого нового проекта. Ниже приведен список обязанностей, которые необходимо учитывать для нашего приложения.
- загружать звуковые ресурсы для использования с эффектами, используя класс CustomLoader
- Как только все звуковые ресурсы загружены, создайте и добавьте 3D-меню на сцену.
- прослушайте события FullScreen и сообщите об этом UserInterface3D
- добавить несколько случайных звуковых эффектов, чтобы улучшить атмосферу
- прослушайте UserInterface3D.START_GAME, чтобы узнать, когда загружать спрайт или видеоклип, представляющий игру
- загрузить UserInterface3D обратно на сцену снова, когда игровой спрайт был удален
Обратите внимание, что для второй ответственности этого класса мы сначала будем использовать класс Tester, а затем заменим его классом UserInterface3D. Тестер будет использоваться для создания и тестирования трехмерных классов по мере их создания, а UserInterface3D объединит их все в одно законченное приложение.
Зайдите в декларацию пакета и замените все импортированные списки ниже:
импорт flash.display.Sprite; импорт flash.events.Event; импортировать flash.events.FullScreenEvent; импорт flash.events.MouseEvent; импорт flash.events.TimerEvent; импорт flash.media.Sound; импорт flash.media.SoundTransform; импортировать flash.system.Capabilities; import flash.text.TextField; import flash.text.TextFieldAutoSize; импорт flash.utils.Timer;
Все эти импорта будут использованы ко времени завершения проекта. Что касается переменных экземпляра, давайте начнем с 2, _timer, который будет экземпляром Timer, назначенным со случайной задержкой, для воспроизведения звуковых эффектов, чтобы добавить атмосферу в наш проект, и _customLoader для хранения одного экземпляра класса CustomLoader, который будет использоваться загрузить все звуковые активы.
Добавьте следующие строки кода внутри объявления класса над методом конструктора:
private var _customLoader: CustomLoader; частный случай _ Таймер: Таймер;
Шаг 7: Инициализация класса документа
По-прежнему в FlashDevelop, чуть ниже, где в методе init () написано «точка входа», добавьте следующие строки кода:
приватная функция init (e: Event = null): void { removeEventListener (Event.ADDED_TO_STAGE, init); //входная точка _customLoader = CustomLoader.getInstance (); _customLoader.addEventListener (CustomLoader.ALL_LOADS_COMPLETE, onLoad); _customLoader.addSound ('soundAssets / background2.mp3'); _customLoader.addSound ('soundAssets / staticNoise3.mp3'); _customLoader.addSound ('soundAssets / buttonShow.mp3'); _customLoader.addSound ('soundAssets / menuExpand.mp3'); _customLoader.addSound ('soundAssets / backgroundFlash.mp3'); _customLoader.addSound ('soundAssets / menuCollapse.mp3'); _customLoader.addSound ('soundAssets / buttonOver.mp3'); _customLoader.addSound ('soundAssets / buttonFlash.mp3'); _customLoader.addSound ('soundAssets / buttonClick.mp3'); _customLoader.addSound ('soundAssets / randomEcho.mp3'); _customLoader.startLoading (); }
Для тех из вас, кто не знаком с классом CustomLoader, он в основном используется для загрузки визуальных и звуковых ресурсов. Он основан на шаблоне Singleton, чтобы убедиться, что есть только один экземпляр, который будет содержать все внешние ресурсы для проекта. Мой другой учебник по созданию вступлений с PV3D, связанный здесь , содержит подробную информацию по созданию этого класса.
Его список обязанностей:
- загрузить внешние активы (отображать и звуковые активы).
- выдать список имен всех активов, которые были загружены.
- отправьте событие CustomLoader.ALL_LOADS_COMPLETE, когда все ресурсы были успешно загружены.
- предоставить актив по запросу.
- если что-то пойдет не так во время загрузки, отправьте сообщение об ошибке.
Чтобы начать использовать класс 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.
Шаг 8: Тестирование экземпляра CustomLoader
Для простого теста давайте воспроизведем случайный звуковой ресурс, получив доступ ко всем именам активов, которые в данный момент хранятся в экземпляре CustomLoader. Добавьте следующие строки кода ниже метода init ():
приватная функция onLoad (e: Event): void { var soundArray: Array = new Array; var namesArray: Array = CustomLoader (e.target) .names; for (var i: uint = 0; i <namesArray.length; i ++) { var sound: Sound = CustomLoader (e.target) .getSound (nameArray [i]) if (sound! = null) soundArray.push (sound); } soundArray [int (Math.random () * soundArray.length)]. play (); }
Теперь, когда вы запускаете проект, вы должны услышать случайный звук. Запустите его еще несколько раз, и вы, вероятно, услышите другой звук каждый раз.
Для Flash создайте новый класс с именем «Main», где вы сохранили ваш interface3D.fla, и используйте его в качестве класса Document. Импорт обычно генерируется FlashDevelop автоматически, но, поскольку вы используете Flash для создания своих классов, просто добавьте их все сейчас, и вы увидите, для чего они будут использоваться позже. Скопируйте код ниже и замените весь код внутри нового класса:
пакет { импорт flash.display.Sprite; импорт flash.events.Event; импортировать flash.events.FullScreenEvent; импорт flash.events.MouseEvent; импорт flash.events.TimerEvent; импорт flash.media.Sound; импорт flash.media.SoundTransform; импортировать flash.system.Capabilities; import flash.text.TextField; import flash.text.TextFieldAutoSize; импорт flash.utils.Timer; Открытый класс Main расширяет Sprite { private var _customLoader: CustomLoader; частный случай _ Таймер: Таймер; публичная функция Main (): void { if (stage) init (); addEventListener (Event.ADDED_TO_STAGE, init); } публичная функция init (e: Event = null): void { removeEventListener (Event.ADDED_TO_STAGE, init); _customLoader = CustomLoader.getInstance (); _customLoader.addEventListener (CustomLoader.ALL_LOADS_COMPLETE, onLoad); _customLoader.addSound ('soundAssets / background2.mp3'); _customLoader.addSound ('soundAssets / staticNoise3.mp3'); _customLoader.addSound ('soundAssets / buttonShow.mp3'); _customLoader.addSound ('soundAssets / menuExpand.mp3'); _customLoader.addSound ('soundAssets / backgroundFlash.mp3'); _customLoader.addSound ('soundAssets / menuCollapse.mp3'); _customLoader.addSound ('soundAssets / buttonOver.mp3'); _customLoader.addSound ('soundAssets / buttonFlash.mp3'); _customLoader.addSound ('soundAssets / buttonClick.mp3'); _customLoader.addSound ('soundAssets / randomEcho.mp3'); _customLoader.startLoading (); } приватная функция onLoad (e: Event): void { var soundArray: Array = new Array; var namesArray: Array = CustomLoader (e.target) .names; for (var i: uint = 0; i <namesArray.length; i ++) { var sound: Sound = CustomLoader (e.target) .getSound (namesArray [i]); если (звук! = ноль) { soundArray.push (sound); } } soundArray [int (Math.random () * soundArray.length)]. play (); } } }
Теперь запустите приложение, нажав CTRL + ENTER.
Большой! Теперь мы знаем, что CustomLoader работает! Давайте двигаться дальше.
Шаг 9: Генерация звуковых эффектов для добавления атмосферы
Замените содержимое метода onLoad () следующим кодом:
var sound: Sound = _customLoader.getSound ('background2'); sound.play (0, 100); createRandomNoise ();
Здесь мы присваиваем локальной переменной ‘sound’ экземпляр background2.mp3 и воспроизводим его 100 раз. Затем вызывается метод createRandomNoise (). Добавьте следующий код ниже метода onLoad ():
приватная функция createRandomNoise (): void { _timer = новый таймер (getRandomInRange (5000, 20000, false), 1); _timer.addEventListener (TimerEvent.TIMER_COMPLETE, onTimerComplete); _timer.start (); }
Добавьте метод onTimerComplete () ниже метода createRandomNoise ().
приватная функция onTimerComplete (e: TimerEvent): void { var sound: Sound = _customLoader.getSound ('randomEcho'); sound.play (0, 0, новый SoundTransform (Math.random () * .7)); createRandomNoise (); }
Для завершения класса добавьте статический метод getRandomInRange (). Этот полезный метод объявлен статическим, чтобы максимизировать его доступность. Он просто генерирует случайное число между $ min и $ max и возвращает его:
- округляется, если третий параметр оставлен по умолчанию,
- как число с плавающей запятой, если для третьего параметра установлено значение false.
Добавьте следующие строки кода ниже метода onTimerComplete ():
публичная статическая функция getRandomInRange ($ min: число, $ max: число, $ округлено: логическое = true): число { if ($ округлено) возвращает Math.round (Math.random () * ($ max - $ min) + $ min); иначе возвращаем Math.random () * ($ max - $ min) + $ min; }
Все, что делает метод createRandomNoise () — назначает новый экземпляр Timer _timer со случайным интервалом от 5 до 20 секунд. Затем слушатель onTimerComplete запускается каждый раз, когда завершается таймер, и именно здесь воспроизводится звук «randomEcho», и, как вы можете видеть, генерируемый звук имеет переменную громкость от 0 до 0,7. Затем он снова вызывает метод createRandomNoise (), чтобы запустить новый таймер. Это создает какой-то случайный звуковой цикл с переменным интервалом. Идите вперед и запустите тест, если все работает. Если все прошло хорошо, вы должны услышать звуковые эффекты в фоновом режиме при запуске программы.
Сохраните свою работу и давайте перейдем к созданию 3D-объектов.
Шаг 10: Создание класса тестера
Если вы используете Flash CS3 +, опять же, просто следуйте инструкциям. Инструкции для Flash CS3 + будут продолжены на шаге 13.
Как упоминалось ранее, этот класс будет использоваться для тестирования 3D-объектов. Этот класс будет унаследован от BasicView, что делает быстрый 3D-шаблон готовым к использованию. В FlashDevelop нажмите «Просмотр»> «Диспетчер проектов», щелкните правой кнопкой мыши папку \ src \ и выберите «Добавить»> «Новый класс».
Откроется окно New Actionscript Class. В качестве имени введите «Tester», для базового класса нажмите «Обзор» и введите «org.papervision3d.view.BasicView». Нажмите «ОК», чтобы закончить.
Это простой класс. Его обязанности заключаются в следующем:
- Добавьте простую трехмерную перспективу.
- Создайте простой 3D-объект в качестве прототипа в качестве отправной точки для создания пользовательских классов DisplayObject3D.
- Протестируйте каждый пользовательский DisplayObject3D, созданный при их создании.
Добавьте следующий импорт в скобки пакета перед объявлением класса:
импорт flash.events.Event; import org.papervision3d.core.math.Number2D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.special.Letter3DMaterial; import org.papervision3d.materials.special.VectorShapeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.special.Graphics3D; import org.papervision3d.objects.special.VectorShape3D; import org.papervision3d.typography.Font3D; import org.papervision3d.typography.Text3D; import org.papervision3d.view.BasicView; import org.papervision3d.view.layer.ViewportLayer;
Шаг 11: Переменные экземпляра тестера
Теперь добавьте следующие частные переменные экземпляра в объявление Class:
приватная переменная _rotX: Number = .1; приватная переменная _rotY: Number = .1; частная переменная _camPitch: Number = 90; частный var _camYaw: номер = 270; приватная переменная _easOut: Number = .1;
Эти 5 переменных будут использоваться для перемещения камеры по орбите. Объекты, добавленные в сцену, не будут двигаться, но будут выглядеть так, поскольку камера будет перемещаться вокруг них. Мы добавим другие переменные при разработке соответствующих им классов DisplayObject3D. Когда мы доберемся до UserInterface3D, у нас будут объекты вращаться и вместо этого держать камеру в неподвижном положении.
Шаг 12: Конструктор Тестера
Конструктор вызовет 2 метода для запуска, во-первых, метод init (), который будет обрабатывать общую инициализацию, и, во-вторых, startRendering (), который запустит движок 3D-визуализации Papervision. Добавьте следующие строки кода в метод конструктора:
в этом (); startRendering ();
Шаг 13: Добавление трехмерных экранных объектов
Этот метод позаботится об инициализации трехмерных объектов, которые мы собираемся создать. А пока давайте добавим простой DisplayObject3D в сцену в качестве разминки. Добавьте следующие строки кода ниже метода «Конструктор тестера»:
приватная функция init (): void { addSimpleDO3D (); }
Метод addSimpleDO3D () добавит трехмерную векторную графику вместе с трехмерным текстом в сцену. Это послужит прототипом для пользовательских классов, которые мы вскоре сделаем. Добавьте код ниже метода init ():
приватная функция addSimpleDO3D (): void { // создаем 3d векторную форму var material: VectorShapeMaterial = new VectorShapeMaterial (); var vs3D: VectorShape3D = новый VectorShape3D (материал); var g: Graphics3D = vs3D.graphics; g.beginFill (0xFF000); g.lineStyle (1, 0x0000FF); g.moveTo (-199, 106); g.lineTo (-199, -106); g.lineTo (199, -106); g.lineTo (199,106); g.lineTo (-199,106); g.endFill (); var vLayer: ViewportLayer = viewport.getChildLayer (vs3D); vLayer.alpha = .6; // создаем 3d текст var nameString: String = 'sample'; var letterMaterial: Letter3DMaterial = new Letter3DMaterial (0x00FF00); var font3D: Font3D = новое тысячелетие; var text3D: Text3D = новый Text3D (nameString, font3D, letterMaterial, nameString); text3D.x = -650; text3D.y = 10; // мы используем эту настройку y для шрифта Millenia text3D.z = -25; text3D.align = 'left'; var tLayer: ViewportLayer = viewport.getChildLayer (text3D); tLayer.alpha = .6; // используя пустой DisplayObject3D для размещения как трехмерной графики, так и текста var do3D: DisplayObject3D = новый DisplayObject3D; do3D.addChild (vs3D); do3D.addChild (text3D); // добавляем DisplayObject3D, содержащий как векторную графику, так и текст в сцену scene.addChild (do3D); }
Во-первых, мы создаем 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-й текст, который он напишет, находится в строке String. Здесь мы передаем ему переменную nameString.
- Далее letterMaterial типа LetterMaterial. При создании экземпляра этого класса мы передаем цвет 0x00FF00 (зеленый). Если оставить его в покое, параметры по умолчанию будут розовыми для цвета и 1 для альфы (полная непрозрачность).
- Третьей переменной font3D типа Font3D назначается экземпляр класса Millenia.as.
- 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 ():
var tester: Tester = новый тестер; addChild (тестер);
Теперь запустите его, чтобы просмотреть продукт. Это должно выглядеть как вырез ниже со звуковыми эффектами, играющими на заднем плане. Если вы используете Flash, просто добавьте код выше в Main.as и следуйте до конца этого шага.
Давайте добавим 1 последний метод, прежде чем перейти к созданию нашего первого пользовательского класса DisplayObject3D. Это позаботится о перемещении камеры и даст нам эту трехмерную перспективу. Добавьте следующие строки кода ниже метода addSimpleDO3D ():
переопределить защищенную функцию onRenderTick (event: Event = null): void { var xDist: Number = mouseX - stage.stageWidth * .5; var yDist: Number = mouseY - stage.stageHeight * .5; _camPitch + = ((yDist * _rotX) - _camPitch + 90) * _easOut; _camYaw + = ((xDist * _rotY) - _camYaw + 270) * _easOut; camera.orbit (_camPitch, _camYaw); super.onRenderTick (событие); }
Этот метод взят из суперкласса 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. Скопируйте приведенный ниже код, сохраните его снова и запустите.
пакет { импорт flash.events.Event; import org.papervision3d.core.math.Number2D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.special.Letter3DMaterial; import org.papervision3d.materials.special.VectorShapeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.special.Graphics3D; import org.papervision3d.objects.special.VectorShape3D; import org.papervision3d.typography.Font3D; import org.papervision3d.typography.Text3D; import org.papervision3d.view.BasicView; import org.papervision3d.view.layer.util.ViewportLayerSortMode; import org.papervision3d.view.layer.ViewportLayer; Открытый класс Tester расширяет BasicView { приватная переменная _rotX: Number = .1; приватная переменная _rotY: Number = .1; частная переменная _camPitch: Number = 90; частный var _camYaw: номер = 270; приватная переменная _easOut: Number = .1; Тестер публичной функции () { в этом (); startRendering (); } приватная функция init (): void { addSimpleDO3D (); } приватная функция addSimpleDO3D (): void { // создаем 3d векторную форму var material: VectorShapeMaterial = new VectorShapeMaterial (); var vs3D: VectorShape3D = новый VectorShape3D (материал); var g: Graphics3D = vs3D.graphics; g.beginFill (0xFF0000); g.lineStyle (1, 0x0000FF); g.moveTo (-199, 106); g.lineTo (-199, -106); g.lineTo (199, -106); g.lineTo (199,106); g.lineTo (-199,106); g.endFill (); var vLayer: ViewportLayer = viewport.getChildLayer (vs3D); vLayer.alpha = .6; // создаем 3d текст var nameString: String = 'sample'; var letterMaterial: Letter3DMaterial = new Letter3DMaterial (0x00FF00); var font3D: Font3D = новое тысячелетие; var text3D: Text3D = новый Text3D (nameString, font3D, letterMaterial, nameString); text3D.x = -650; text3D.y = 10; // мы используем эту настройку y для Millenia text3D.z = -25; text3D.align = 'left'; var tLayer: ViewportLayer = viewport.getChildLayer (text3D); tLayer.alpha = .6; // используя пустой DisplayObject3D для размещения как трехмерной графики, так и текста var do3D: DisplayObject3D = новый DisplayObject3D; do3D.addChild (vs3D); do3D.addChild (text3D); // добавляем DisplayObject3D, содержащий как векторную графику, так и текст в сцену scene.addChild (do3D); } переопределить защищенную функцию onRenderTick (event: Event = null): void { var xDist: Number = mouseX - stage.stageWidth * .5; var yDist: Number = mouseY - stage.stageHeight * .5; _camPitch + = ((yDist * _rotX) - _camPitch + 90) * _easOut; _camYaw + = ((xDist * _rotY) - _camYaw + 270) * _easOut; camera.orbit (_camPitch, _camYaw); super.onRenderTick (событие); } } }
Если вы столкнулись с проблемами, просто сравните ваш код с законченными классами, включенными в исходную загрузку.
Шаг 14. Создание пользовательского базового класса DisplayObject3D — UIComponent3D
Этот класс должен упростить добавление нарисованного VectorShape3D с произвольно видимым text3d в сцену. Он также будет отвечать за сортировку «z». Это будет частью решения, которое мы обсудим позже. Он будет добавлять, удалять и отправлять InteractiveScen3DEvents, рисовать трехмерные векторы и вычислять их размеры. Этот класс будет служить в качестве суперкласса для всех различных визуальных ресурсов (включая кнопки), используемых в этом проекте. Вот список его обязанностей:
- обеспечить свойства ширины и высоты, переведенные в систему измерения единиц измерения PV3D.
- нарисовать собственный вектор vetershape3d и получить доступ к его ViewportLayer для применения эффектов.
- добавить text3D, также получить доступ к его ViewportLayer для применения эффектов.
- организовать сортировку z.
- добавьте прослушиватели, удалите прослушиватели и отправьте InteractiveScene3DEvents.
Для FlashDevelop создайте новый класс, назовите его UIComponent3D и сделайте так, чтобы он расширял DisplayObject3D. Смотрите Шаг 10 для повышения квалификации.
Для Flash создайте класс внутри папки, которую вы использовали для interface3D.fla.
Выделите весь код внутри класса и замените его следующими строками:
пакет { import org.papervision3d.core.math.Number2D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.special.Letter3DMaterial; import org.papervision3d.materials.special.VectorShapeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.special.Graphics3D; import org.papervision3d.objects.special.VectorShape3D; import org.papervision3d.typography.Font3D; import org.papervision3d.typography.Text3D; import org.papervision3d.view.layer.ViewportLayer; import org.papervision3d.view.Viewport3D; открытый класс UIComponent3D расширяет DisplayObject3D { защищенные переменные _координаты: массив; // содержит массив Number2D, используемый для рисования VectorShape3D защищенная переменная _fillColor: uint = 0x2D2D2D; // fillColor для использования в VectorShape3D защищенная переменная _fillAlpha: Number = .6; // fillAlpha для использования в VectorShape3D защищенная переменная _lineColor: uint = 0x007500; // lineColor для использования в VectorShape3D защищенная переменная _lineAlpha: число = 0; // lineAlpha для использования в VectorShape3D защищенная переменная _lineThickness: Number = 2; // lineThickness для использования для VectorShape3D защищенный var _layerIndex: Number = 1; // часть сортировки 'z' защищенный var _viewport: Viewport3D; // часть доступа к ViewportLayer объекта DisplayObject3D защищенная переменная _interfaceGraphic: VectorShape3D; //рисование защищенный var _interfaceLayer: ViewportLayer; // слой VectorShape3D для применения фильтров и эффектов защищенная переменная _text3D: Text3D; // 3d текст защищенный var _textLayer: ViewportLayer; // слой Text3D для применения фильтров и эффектов защищенная переменная _width: число; // используется подклассом Button3D - об этом вы узнаете позже защищенная переменная _height: число; // то же, что и выше защищенный var _showText: Boolean; // если установлено значение true во время создания экземпляра, Text3D будет добавлен в список отображения открытая функция UIComponent3D ($ name: String, $ viewport: Viewport3D, $ координаты: массив, $ showText: Boolean = false) { супер ($ name); _viewport = $ viewport; _coordinates = $ координаты; _showText = $ showText; } } }
После объявления пакета идет импорт всех необходимых классов. Затем идет объявление класса. Ниже вы видите все защищенные переменные, необходимые для его функциональности. Комментарии перечислены справа от каждой переменной для описания использования. Затем приходит конструктор. Требуются первые 3 параметра, за которыми следует необязательный 4-й параметр. Важно иметь имя для каждого DisplayObject3D для справки. Параметр $ viewport необходим для доступа к ViewportLayer Text3D и VectorShape3D, к которым будут применены эффекты. Параметр координат представляет собой массив Number2D, используемый для рисования. 4-й параметр позволяет показать или скрыть 3D-текст.
Конструктор вызывает super (), чтобы назначить имя для DisplayObject3D, а остальные настраиваемые свойства сохраняются для каждого экземпляра UIComponent3D.
Шаг 15: Визуальная настройка UIComponent3D
После создания экземпляра UIComponent3D мы можем настроить свойства VectorShape3D перед рисованием. Добавьте следующие строки кода после конструктора:
открытый набор функций fillColor ($ value: uint): void { _fillColor = $ value; } открытый набор функций fillAlpha ($ value: Number): void { _fillAlpha = $ value; } открытый набор функций lineColor ($ value: uint): void { _lineColor = $ value; } открытый набор функций lineAlpha ($ value: Number): void { _lineAlpha = $ value; } открытая функция set lineThickness ($ value: Number): void { _lineThickness = $ value; }
Это все неявные методы установки. Вы можете прочитать больше об этих методах, включая их аналоги здесь . Вы увидите их в действии позже.
Шаг 16: Инициализация UIComponent3D
После того, как мы настроили визуальные свойства, мы можем инициализировать экземпляр UIComponent3D извне. Пример покажет, почему у нас есть этот набор в качестве открытых методов. Здесь setDimensions () вызывается для установки его ширины и высоты. Затем вызывается метод createInterface () для рисования VectorShape3D и, наконец, вызывается createText () для создания Text3D. Добавьте следующий метод выше методов получения:
публичная функция init (): void { setDimensions (); createInterface (_coordinates); createText (); }
Шаг 17: Вычисление свойств ширины и высоты UIComponent3D
Нам нужно получить эти свойства для создания интерактивной плоскости позже, когда мы расширим это для нашего класса Button3D. Как вы знаете, объекты Papervision DisplayObject не имеют свойств width и height, поэтому мы добавляем их в качестве пользовательских свойств экземпляра, унаследованных всеми подклассы. Для ширины мы используем простую математику и добавляем самую дальнюю позицию «x» слева от центра, а самую дальнюю позицию «x» — справа. То же самое относится и к высоте. Добавьте код после метода init ():
защищенная функция setDimensions (): void { var minWidth: Number = 0, minHeight: Number = 0, maxWidth: Number = 0, maxHeight: Number = 0; для каждого (var n2d: Number2D в _coordinates) { minWidth = n2d.x <minWidth? n2d.x: minWidth; minHeight = n2d.y <minHeight? n2d.y: minHeight; maxWidth = n2d.x> maxWidth? n2d.x: maxWidth; maxHeight = n2d.y> maxHeight? n2d.y: maxHeight; } _width = Math.abs (minWidth) + maxWidth; _height = Math.abs (minHeight) + maxHeight; }
Чтобы эти защищенные свойства были доступны извне, давайте добавим для них также неявные методы получения. Добавьте методы ниже над другими неявными получателями в нижней части класса:
публичная функция get width (): Number {return _width; } публичная функция get height (): Number {return _height; }
Шаг 18: Рисование VectorShape3D
Этот метод вызывается следующим внутри метода init (). Он заботится о добавлении трехмерной графики в UIComponent3D и назначает свой ViewportLayer _interfaceLayer для применения эффектов позже. Помните метод addSimpleDO3D () в классе Tester. Кроме того, теперь он использует массив координат Number2D для рисования. Добавьте следующие строки кода ниже setDimensions ():
защищенная функция createInterface ($ array: Array): void { var material: VectorShapeMaterial = new VectorShapeMaterial (); _interfaceGraphic = new VectorShape3D (материал); var g: Graphics3D = _interfaceGraphic.graphics; g.beginFill (_fillColor, _fillAlpha); g.lineStyle (_lineThickness, _lineColor, _lineAlpha); for (var i: uint = 0; i <$ array.length; i ++) { if (i == 0) g.moveTo ($ array [i] .x, $ array [i] .y); иначе g.lineTo ($ array [i] .x, $ array [i] .y); } g.endFill (); _interfaceLayer = _viewport.getChildLayer (_interfaceGraphic); setLayerIndex (_interfaceLayer, _layerIndex); addChild (_interfaceGraphic); }
Внутри метода есть вызов метода setLayerIndex (), который является частью нашей проблемы с сортировкой z. Он назначает переданный в ViewportLayer параметр layerIndex переданному параметру index. Добавьте его ниже конца метода createInterface ().
защищенная функция setLayerIndex ($ layer: ViewportLayer, $ index: Number): void { $ layer.layerIndex = $ index; }
Шаг 19: Добавление Text3D
Это также было частью метода addSimpleDO3D (), мы просто разделили его для большего контроля и для простоты. Добавьте код над методом setLayerIndex ():
защищенная функция createText (): void { var материал: Letter3DMaterial = новый Letter3DMaterial (0xDDFFFF); var font3D: Font3D = новое тысячелетие; _text3D = новый Text3D (имя, font3D, материал, имя); _textLayer = _viewport.getChildLayer (_text3D); setLayerIndex (_textLayer, _layerIndex + 1); // назначаем на фронт _text3D.x = -850; _text3D.y = 10; _text3D.z = -25; _text3D.align = 'left'; if (_showText == true) addChild (_text3D); }
Метод setLayerIndex () вызывается снова, на этот раз передается в ViewportLayer Text3D, и ему присваивается значение _layerIndex + 1. При этом Text3D всегда рисуется перед VectorShape3D. Также обратите внимание, как мы проверяем, что для _showText установлено значение true, по умолчанию это значение равно false как последний параметр метода Constructor.
Шаг 20. Добавление и удаление прослушивателей InteractiveScene3DEvent и их рассылка
Для Papervision это событие, которое вы хотите услышать для интерактивности. Добавьте следующие коды ниже метода setLayerIndex ():
Защищенная функция addMouseListeners ($ do3D: DisplayObject3D): void { $ do3D.addEventListener (InteractiveScene3DEvent.OBJECT_OVER, onObjectOver); $ do3D.addEventListener (InteractiveScene3DEvent.OBJECT_OUT, onObjectOut); $ do3D.addEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onObjectClick); } защищенная функция removeMouseListeners ($ do3D: DisplayObject3D): void { $ do3D.removeEventListener (InteractiveScene3DEvent.OBJECT_OVER, onObjectOver); $ do3D.removeEventListener (InteractiveScene3DEvent.OBJECT_OUT, onObjectOut); $ do3D.removeEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onObjectClick); } public function onObjectOver (e: InteractiveScene3DEvent = null): void {dispatchEvent (new InteractiveScene3DEvent (e.type, e.target as DisplayObject3D)); } public function onObjectOut (e: InteractiveScene3DEvent = null): void {dispatchEvent (new InteractiveScene3DEvent (e.type, e.target as DisplayObject3D)); } public function onObjectClick (e: InteractiveScene3DEvent = null): void {dispatchEvent (new InteractiveScene3DEvent (e.type, e.target as DisplayObject3D)); }
Первые 2 упрощают добавление и удаление событий MouseOver, MouseOut и MouseClick. Последние 3 заботятся об их отправке. Все это помогает расширяющемуся подклассу — Button3D. Я решил поместить эти методы в UIComponent3D, чтобы сосредоточить Button3D на своих других обязанностях.
Шаг 21: Внешний доступ к ViewportLayers для эффектов и фильтров
Добавьте методы ниже, чтобы позволить другим классам применять эффекты для каждого UIComponent3D. Это будет использоваться DistortionEffect3D, который вы создадите позже.
публичная функция get interfaceLayer (): ViewportLayer {return _interfaceLayer; } публичная функция get textLayer (): ViewportLayer {return _textLayer; }
Шаг 22: Внешний доступ к Text3D для позиционирования
Нам придется вручную корректировать положение для каждого Text3D, когда мы создадим пару классов-потомков, расширяющих Button3D. Добавьте код ниже после метода get textLayer ():
публичная функция get text3D (): Text3D {return _text3D; }
Это завершает наш класс UIComponent3D! Сохраните его, прежде чем перейти к следующему шагу.
Шаг 23: Milestone Testing из UIComponent3D
Вернитесь к классу Tester и закомментируйте вызов метода addSimpleDO3D (). Затем добавьте вызов метода addCustomDO3D () под ним. Затем добавьте метод, указанный ниже, после метода addSimpleDO3D ():
приватная функция addCustomDO3D (): void { _uic = новый UIComponent3D ( 'образец', окно просмотра, [новый Number2D (-199, 106), новый Number2D (-199, -106), новый Number2D (199, -106), новый Number2D (199, 106), новый Number2D (-199, 106)], правда ); _uic.init (); _uic.text3D.x = -650; // визуально центрировать текст scene.addChild (_uic); }
Помните, как мы настраивали конструктор 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 () и добавьте приведенный ниже код, прежде чем что-либо еще.
viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
Убедитесь, что следующий импорт включен в пакет Tester, прежде чем снова запускать приложение.
import org.papervision3d.view.layer.util.ViewportLayerSortMode;
Хорошо!Это решает проблему сортировки «z». Опять же, если у вас есть ошибки, проверьте свой код по завершенным классам, включенным в исходную загрузку. Если все прошло хорошо, давайте начнем создавать класс Button3D.
Шаг 24: Создание Button3D
Для Button3D вместо того, чтобы просто отправлять события мыши, а затем расширять его для добавления эффектов, мы сделаем все это за один раз. Кроме того, это одна из причин, по которой мы добавили слушателей в суперкласс Button3D — UIComponent3D. Он наследует от UIComponent3D, затем добавляет свою собственную функциональность. Вот список его обязанностей:
- играть звуковые эффекты для мыши и мыши.
- добавить интерактивную плоскость, которая будет вызывать события мыши.
- применять эффекты для наведения мыши, мыши и щелчка мыши.
- обеспечить внешнее управление для добавления и удаления слушателей событий мыши.
- обеспечить внешнее управление для удаления обработчиков щелчков мыши, используемых при создании кнопок, которые слушают только при наведении курсора мыши и при отсутствии мыши для прокрутки Text3D, как вы видели в меню «О программе».
Создайте новый класс и назовите его Button3D. Сделайте так, чтобы он расширил UIComponent3D и скопировал в него приведенный ниже код для начала. Я ожидаю, что вы уже знаете, как создавать новые классы независимо от того, какой редактор вы используете.
пакет { import com.greensock.TweenMax; импорт flash.events.TimerEvent; импорт flash.filters.BlurFilter; импортировать flash.filters.GlowFilter; импорт flash.media.Sound; импорт flash.media.SoundTransform; импорт flash.utils.Timer; import org.papervision3d.core.math.Number2D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.view.Viewport3D; Открытый класс Button3D расширяет UIComponent3D { public static const OVER_POSITION: Number = -50; public static const OUT_POSITION: Number = 0; защищенная переменная плоскость: плоскость; // будет работать как интерактивный объект, который будет прослушивать события мыши protected var _buttonOverSound: Звук // воспроизводится, когда мышь находится над этой кнопкой защищенная переменная _buttonClickSound: Sound; // играется, когда мышь нажимает эту кнопку защищенная переменная _soundTransform: SoundTransform; // используется для регулировки громкости защищенный var _noClick: Boolean; // для использования подкласса (скроллер) открытая функция Button3D ($ name: String, $ viewport: Viewport3D, $ координаты: массив = null, $ showText: Boolean = true) { //Начни здесь } } }
Как обычно, требуемый импорт находится в верхней части страницы как часть пакета. Внутри объявления класса первые 2 свойства объявлены как открытые статические константы, так как оба будут использоваться внешними классами и классами-потомками. Они для позиционирования «Z» для кнопки. Остальные 5 являются переменными экземпляра, доступными для подклассов. Смотрите комментарии для их использования. Метод конструктора принимает те же параметры, что и суперкласс, на этот раз установка третьего параметра также необязательна. 4-й параметр также изменен, чтобы показать текст по умолчанию.
Шаг 25: Конструктор Button3D
Добавьте код ниже внутри метода конструктора:
if ($ arguments == null) _coordinates = [ новый Number2D (-430, 65), новый Number2D (-450, 35), новый Number2D (-450, -35), новый Number2D (-430, -65), новый Number2D (400, -65), новый Number2D (400, 5), новый Number2D (450, 5), новый Number2D (450, 65), новый Number2D (-430, 65) ] иначе _coordinates = $ координаты; // если $ координаты не равны нулю, присваиваем super ($ name, $ viewport, _coordinates, $ showText); var customLoader: CustomLoader = CustomLoader.getInstance (); _soundTransform = new SoundTransform (.1); _buttonOverSound = customLoader.getSound ('buttonOver'); _buttonClickSound = customLoader.getSound ('buttonClick');
Первое, что он делает, это проверяет, является ли значение $ координаты нулевым, если это так, он назначает свой собственный набор. Таким образом, всякий раз, когда экземпляр этого класса создается с третьим параметром, установленным в нуль, он будет иметь набор координат по умолчанию для рисования. (Я включил в учебник простой инструмент рисования, который можно использовать для генерации этих координат.)
Затем выполняется вызов метода super (), передавая присвоенные значения, которые обрабатываются UIComponent3D. Затем к экземпляру CustomLoader осуществляется доступ к звуковым эффектам, используемым для событий мыши. Громкость звуков, которые мы используем, немного громкая, поэтому мы компенсировали это классом SoundTransform.
Шаг 26: Добавление функциональности в метод createInterface ()
Помимо рисования VectorShape3D, мы также хотим добавить плоскость, которая будет прослушивать события мыши здесь, в Button3D. Мы можем сделать это, переопределив метод createInterface (), унаследованный от UIComponent3D, и применить к нему новые функциональные возможности. Добавьте код ниже после конструктора:
переопределить защищенную функцию createInterface ($ array: Array): void { super.createInterface ($ массив); addInteractivePlane (); }
Это лучший пример, чтобы показать эффективность ООП. Переопределяя унаследованный метод, а затем просто добавляя его, мы избегаем дублирования кода. Все, что мы здесь сделали, это вызвали super.createInterface (), передав параметр, чтобы UIComponent3D сделал свое дело, а затем вызвав addInteractivePlane (), чтобы Button3D добавила плоскость для интерактивности. Добавьте код ниже после метода createInterface ():
защищенная функция addInteractivePlane (): void { _plane = новая плоскость (новый ColorMaterial (0, 0, true), _width, _height); _plane.x = _interfaceGraphic.x; addChild (_plane); активировать (); }
Метод прост. Он назначает новую плоскость с цветом 0 (черный) и альфа 0, чтобы сделать ее полностью прозрачной. Здесь мы используем свойства _width и _height, унаследованные от UIComponent3D. Чтобы создать плоскость, мы просто создаем экземпляр, передав 3 параметра: цветной материал, который мы установили на черный с полной прозрачностью, а затем _width и _height. После создания он помещается в ту же позицию «x», что и унаследованный _interfaceGraphic VectorShape3D. Затем Button3D добавляет его как дочерний элемент и вызывает метод activ (). Здесь вызывается метод activ (), чтобы после создания экземпляра Button3D он автоматически становился интерактивным. Я подробнее расскажу о методах activ () и deActivate (), когда мы их доберемся.
Шаг 27: применение эффектов для отражения интерактивности
Моя любимая часть, создание эффектов! Итак, давайте рассмотрим эффект, которого мы хотим достичь. Чтобы навести курсор мыши, мы хотим, чтобы кнопка приблизилась к камере, воспроизвела звук, на секунду загорелась, а затем снова вернулась в нормальное состояние. Для мыши, мы просто хотим, чтобы кнопка вернулась в исходное положение. Для щелчка мышью мы хотим, чтобы кнопка также вернулась в исходное положение, моргнула 3 раза, а затем отправила событие щелчка кнопки, чтобы меню, содержащее их, не закрывалось до окончания 3 миганий. Давайте начнем с эффекта наведения мыши. Добавьте следующий код ниже метода addInteractivePlane ():
переопределить открытую функцию onObjectOver (e: InteractiveScene3DEvent = null): void { _buttonOverSound.play (0,0, _soundTransform); this.z = OVER_POSITION; _interfaceLayer.filters = [new BlurFilter (5, 5), новый GlowFilter (0xFFFFFF, 1, 15, 15, 2)]; _textLayer.filters = [new BlurFilter (5, 5), новый GlowFilter (0xFFFFFF, 1, 15, 15, 2)]; TweenMax.to ( _interfaceLayer, +0,4, { blurFilter: {blurX: 0, blurY: 0, качество: 1}, glowFilter: {color: 0xFFFFFF, alpha: 0, blurX: 0, blurY: 0, сила: 0, качество: 1} } ); TweenMax.to ( _textLayer, +0,4, { blurFilter: {blurX: 0, blurY: 0, качество: 1}, glowFilter: {color: 0xFFFFFF, alpha: 0, blurX: 0, blurY: 0, сила: 0, качество: 1} } ); super.onObjectOver (е); }
Во-первых, мы воспроизводим звук, назначенный для мыши. Затем мы перемещаем кнопку ‘z’ на 50 единиц ближе к камере. Помните, вы присваивали им свойства ViewportLayer для VectorShape3D и Text3D, когда мы создавали UIComponent3D? Мы используем TweenMax, потому что он имеет дополнительную возможность применения эффектов размытия и свечения, не говоря уже о других, которых нет у TweenLite. Здесь мы немедленно назначаем массив фильтров как _interfaceLayer, так и _textLayer. Это так же просто, как назначить фильтры обычному классу Sprite, так как по сути ViewportLayer является Sprite. TweenMax используется для исчезновения эффектов. Затем выполняется вызов метода onObjectOver () UIComponent3D, передавая то же событие InteractiveScene3DEvent, которое вызвало этот.
Затем, для мыши, добавьте приведенный ниже код после метода onObjectOver ():
переопределить открытую функцию onObjectOut (e: InteractiveScene3DEvent = null): void { super.onObjectOut (е); this.z = OUT_POSITION; }
Все, что это делает, это вызывает метод onObjectOut () UIComponent3D и помещает кнопку обратно в исходное положение.
Теперь для эффекта щелчка мыши. Добавьте следующий метод под методом onObjectOut ():
переопределить открытую функцию onObjectClick (e: InteractiveScene3DEvent = null): void { _buttonClickSound.play (0,0, _soundTransform); this.z = OUT_POSITION; flashText (); // вспомогательный метод, чтобы заставить текст мигать 3 раза деактивировать (); // предотвращает срабатывание более одного раза // отправляется немедленно, чтобы сообщить MainMenu3D, чтобы деактивировать другие Button3D, которые он держит dispatchEvent (новый InteractiveScene3DEvent (InteractiveScene3DEvent.OBJECT_RELEASE)); }
Когда нажимается экземпляр Button3D, первое, что он делает, — это воспроизводит звук. Затем он возвращается в исходное положение «z». Затем вызываются два метода — flashText () и deActivate (). Мы используем InteractiveScene3D.OBJECT_RELEASE, чтобы сообщить MainMenu3D, удерживающему этот Button3D, чтобы он мог отключить все остальные кнопки после того, как выбор уже сделан. Добавьте 2 вспомогательных метода под методом onObjectClick ():
защищенная функция flashText (): void { var timer: Таймер = новый таймер (15, 9); timer.addEventListener (TimerEvent.TIMER, мигает); timer.addEventListener (TimerEvent.TIMER_COMPLETE, dispatchClick); timer.start (); } мигание защищенной функции (e: TimerEvent): void { _text3D.visible =! _text3D.visible; } защищенная функция dispatchClick (e: TimerEvent): void { мигать (е); // сделать текст видимым // отправляется только после завершения анимации кнопки, используется в качестве триггера для фактической обработки функции, вызываемой этой кнопкой super.onObjectClick (новый InteractiveScene3DEvent (InteractiveScene3DEvent.OBJECT_CLICK)); }
Итак, есть еще один вспомогательный метод, помогающий вспомогательному методу flashText (). Эй, все, что нужно для достижения эффекта, верно ?! знак равно
Когда вызывается flashText (), он создает таймер с задержкой 15 миллисекунд, которая повторяется 9 раз. Затем метод blink () назначается в качестве обратного вызова для каждого события TIMER, dispatchClick () назначается в качестве обратного вызова для события TIMER_COMPLETE. каждый раз, когда вызывается метод blink (), видимость _text3D переключается. Это происходит 9 раз, и это выглядит так, как будто текст моргнул очень быстро 3 раза. После завершения таймера blink () вызывается еще раз, чтобы снова сделать _text3D видимым, и отправляется событие onObjectClick.
Шаг 28: Внешние элементы управления для добавления и удаления слушателей MouseEvent
Добавьте следующие строки кода:
публичная функция activ (): пустота { addMouseListeners (_plane); } публичная функция deActivate (): void { removeMouseListeners (_plane); }
Эти методы позволят MainMenu3D контролировать, когда Button3D должен прослушивать события мыши, мыши и нажатия мыши.
Шаг 29: дополнительная функциональность
Зайдите в демонстрационное приложение еще раз и поиграйте с меню About. Обратите внимание, что скроллерам не нужно слушать щелчки мыши. Для этого нам нужно будет добавить функциональность для удаления слушателя щелчка мыши, автоматически добавляемого по умолчанию. Добавьте 2 метода внизу класса:
публичная функция set noClick ($ value: Boolean): void { _noClick = $ value; } переопределить защищенную функцию addMouseListeners ($ do3D: DisplayObject3D): void { super.addMouseListeners ($ do3D); if (_noClick == true) _plane.removeEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onObjectClick); }
Метод set set noClick () просто назначает передаваемый ему логический параметр. Чтобы удалить прослушиватель щелчков, просто вызовите этот метод и передайте значение true перед вызовом метода init () кнопки. Button3D переопределяет метод addMouseListeners () и проверяет, имеет ли свойство _noClick значение true, если это так, он прекращает прослушивание событий щелчка.
Шаг 30: Тестирование вехи Button3D
Вернитесь к Tester.as и закомментируйте вызов метода addCustomDO3D () внутри метода init (). Затем добавьте вызов метода addButton () под ним. Затем добавьте 2 метода, перечисленных ниже, после метода init ():
приватная функция addButton (): void { var b: Button3D = новая Button3D («кнопка 0», область просмотра); b.init (); // не забывайте вызывать это после изменения свойств кнопки b.addEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onButtonClick); scene.addChild (b); } приватная функция onButtonClick (e: InteractiveScene3DEvent): пусто { трассировка («кнопка3d была нажата»); Button3D (e.target) .activate (); }
Сначала он назначает локальную переменную с именем «b» в качестве экземпляра Button3D и передает имя и текст «кнопки 0» и область просмотра. Помните, что последние 2 параметра являются необязательными. Теперь запустите это. Вы должны увидеть что-то вроде выреза ниже:
К сожалению!Нет взаимодействия с мышью ?! Для прослушивания событий мыши, во-первых, нам нужно сделать интерактивный видовой экран. Вернитесь в метод init () Tester и добавьте код под присваиванием sortMode:
viewport.interactive = true;
Это оно!Запустите его снова и посмотрите, как он реагирует на мышь. Метод onButtonClick () сообщает нам, что кнопка нажата с помощью трассировки, а затем мы вызываем Button3D.activate () для кнопки, чтобы она снова прослушивала события мыши. Помните, у нас есть этот набор, чтобы отключить себя, как только кнопка нажата. Кроме того, вы можете изменить скорость миганий, если считаете, что она немного быстрая — см. Шаг 27. Но как только эффекты добавлены, вам, возможно, придется заново отрегулировать их.
Давайте сделаем еще одну кнопку, на этот раз, давайте немного настроим ее, так как последняя имела все свойства по умолчанию. Измените код внутри addButton на то, что мы имеем ниже:
координаты var: Array = [ новый Number2D (-54, 75), новый Number2D (54, 75), новый Number2D (98, 0), новый Number2D (54, -75), новый Number2D (-54, -75), новый Number2D (-98, 0), новый Number2D (-54, 75) ]; var b: Button3D = новая Button3D ('hex', область просмотра, координаты); // переданы в произвольном порядке рисования координат b.fillAlpha = .3; // меняем альфа-значение заполнения с .6 b.lineAlpha = .3; // изменяем альфа-значение строки с 0 b.lineThickness = 5; // изменить значение lineThickness с 2 b.fillColor = 0x808080; // меняем значение цвета заливки с 0x2D2D2D b.lineColor = 0x80FF00; // изменяем значение цвета линии с 0x007500 b.noClick = true; // перестать слушать щелчки мыши b.init (); // после всех модификаций сделать кнопку b.text3D.x = -430; // вручную расположить текст в центре кнопки b.text3D.scale = .75; // масштабируем b.addEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onButtonClick); // тот же слушатель события, не сработает b.addEventListener (InteractiveScene3DEvent.OBJECT_OVER, onButtonOver); // добавлено прослушивание для мыши b.addEventListener (InteractiveScene3DEvent.OBJECT_OUT, onButtonOut); // добавлено прослушивание мыши scene.addChild (b); // добавить в сцену
Чтобы мы знали, что слушатели событий mouse over и mouse out работают, добавьте приведенный ниже код после метода onButtonClick () перед запуском другого теста:
приватная функция onButtonOver (e: InteractiveScene3DEvent): пусто { трассировка («button3d over»); } приватная функция onButtonOut (e: InteractiveScene3DEvent): пусто { трассировка («button3d out»); }
Вот снимок нашего нового Button3D с назначенными нами пользовательскими свойствами.
И это завершает наш класс Button3D. Теперь расслабься, отдохни и возвращайся, когда будешь готов к большему
Шаг 31: Создание главного меню — MainMenu3D
Этот экземпляр DisplayObject3D будет тем, что вы видите в качестве главной страницы, которая открывается при первом запуске приложения. Он содержит 4 кнопки — начать игру, настройки, о, и выход. Он управляет собственной анимацией и обрабатывает события перед отправкой их в иерархию отображения. Вот его список обязанностей:
- создать 2 границы, которые будут служить в качестве оболочки для содержимого
- создать и добавить 4 кнопки и добавить слушателей для них
- подготовиться к вводной анимации
- добавить эффекты и анимацию
- обеспечить внешнее управление для воспроизведения анимации вступления и выхода
- управлять активацией и деактивацией кнопок
- отправлять пользовательские события, запускаемые 4 кнопками, чтобы UserInterface3D мог загрузить соответствующее подменю, иметь основной документ, загрузить спрайт игры или закрыть все приложение
Создайте новый класс и назовите его MainMenu3D. Пусть он расширяет DisplayObject3D. Когда файл класса открыт, просто скопируйте и вставьте приведенный ниже код, заменив содержимое класса.
пакет { импорт com.greensock.easing.Expo; import com.greensock.TweenMax; импорт flash.events.Event; импорт flash.media.Sound; импорт flash.media.SoundTransform; import org.papervision3d.core.math.Number2D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.view.Viewport3D; Открытый класс MainMenu3D расширяет DisplayObject3D { // используется как пользовательское событие, уведомляющее UserInterface3D для загрузки обратно MainMenu3D при нажатии кнопки «Назад» из 2 других подменю public static const BACK_TO_MAIN: String = 'backToMain'; public static const START_GAME_CLICKED: String = 'startGameClicked'; // сообщает UserInterface3D, что нажата кнопка запуска игры public static const SETTINGS_CLICKED: String = 'settingsClicked'; // сообщает UserInterface3D, что была нажата кнопка настроек public static const ABOUT_CLICKED: String = 'aboutClicked'; // сообщает UserInterface3D, что нажата кнопка о public static const EXIT_CLICKED: String = 'exitClicked'; // сообщает UserInterface3D, что была нажата кнопка выхода public static const EXIT_COMPLETE: String = 'exitComplete'; // сообщает UserInterface3D, что анимация выхода из меню завершена защищенная переменная _topNav: UIComponent3D; // для верхней границы, содержащей 4 кнопки защищенная переменная _bottomNav: UIComponent3D; // для нижней границы, охватывающей 4 кнопки защищенный var _viewport: Viewport3D; // передается из Tester или UserInterface3D для доступа к ViewportLayers для применения эффектов защищенная переменная _ButtonPosY: Array = [220, 70, -80, -230]; // кнопка y положения сверху вниз protected var _buttonTitles: Array = ['start game', 'settings', 'about', 'exit']; // названия кнопок и текст защищенная переменная _buttonArray: Array; // содержит ссылки на 4 кнопки // класс пользовательских эффектов, который мы создадим позже, воспроизведите предварительный просмотр по ссылке вверху страницы, чтобы увидеть это /// private var _distortion: DistortionEffect3D; // оставь это закомментированным публичная функция MainMenu3D ($ name: String, $ viewport: Viewport3D) { //Начни здесь } } }
Во-первых, требуемый импорт внутри объявления пакета, затем идут переменные экземпляра и константы класса.
Шаг 32: Конструктор MainMenu3D
Конструктор принимает 2 обязательных параметра: $ name и $ viewport. super () вызывается для назначения $ name для экземпляра DisplayObject3D. И $ viewport сохраняется для справки позже. Добавьте код ниже внутри метода конструктора:
супер ($ name); _viewport = $ viewport; в этом ();
Шаг 33: Инициализация экземпляра
Метод init () запускает 3 других метода, которые абстрагируют создание границ, кнопок и эффекта искажения. Добавьте код ниже после конструктора:
защищенная функция init (): void { createFrame (); addButtons (); setMenuEffect (); }
Первый метод createFrame () просто добавляет 2 границы как дочерние. Мы используем UIComponent3D, так как все, что им нужно, это визуальные компоненты. Добавьте следующий код ниже метода init ():
защищенная функция createFrame (): void { _topNav = новый UIComponent3D ( 'TopNav', _viewport, [ новый Number2D (-400, 26), новый Number2D (-360, 26), новый Number2D (-329, 53), новый Number2D (60, 53), новый Number2D (90, 26), новый Number2D (400, 26), новый Number2D (450, -13), новый Number2D (450, -53), новый Number2D (400, -53), новый Number2D (360, -33), новый Number2D (-2, -33), новый Number2D (-35, -53), новый Number2D (-295, -53), новый Number2D (-450, -53), новый Number2D (-400, 26) ] ); _topNav.fillColor = 0xCCCC00; // изменить цвет по умолчанию на оливково-зеленый _bottomNav = новый UIComponent3D ( 'BottomNav', _viewport, [ новый Number2D (-450, 33), новый Number2D (-50, 33), новый Number2D (-20, 7), новый Number2D (376, 7), новый Number2D (390, 33), новый Number2D (450, 33), новый Number2D (395, -33), новый Number2D (-402, -33), новый Number2D (-450, 33) ] ); _topNav.init (); _bottomNav.init (); addChild (_topNav); addChild (_bottomNav); }
Метод addButtons () заботится о добавлении 4 кнопок. Добавьте код ниже, следующий:
защищенная функция addButtons (): void { _buttonArray = []; для (var i: uint = 0; i <_buttonTitles.length; i ++) { кнопка var: Button3D = новая Button3D (_buttonTitles [i], _viewport); button.addEventListener (InteractiveScene3DEvent.OBJECT_CLICK, onButtonClick); /// button.addEventListener (InteractiveScene3DEvent.OBJECT_RELEASE, onButtonRelease); /// button.y = _buttonPosY [i]; _buttonArray.push (кнопка); button.init (); // не забудьте вызвать init () для любого объекта, который наследуется от UIComponent3D, после настройки addChild (кнопка); } }
Здесь _buttonArray назначается новый массив для хранения ссылок на 4 кнопки. По мере итерации _buttonTitles слушатели для OBJECT_CLICK и OBJECT_RELEASE добавляются для каждой созданной кнопки. затем они позиционируются на оси ‘y’ на основе _buttonPosY для текущей итерации. Помните, как мы настраивали метод onObjectClick () для Button3D, 1-й позаботится о дополнительных анимационных эффектах для кнопки, а другой распространяется до MainMenu3D. Вы увидите его использование, когда мы перейдем к обработчикам событий позже.
Наконец, метод setMenuEffect (). Добавьте код ниже:
защищенная функция setMenuEffect (): void { // оставьте пока пустым }
Здесь мы добавим эффект искажения. А пока оставьте это, пока мы не создадим собственный класс DistortionEffect3D. Мы сделаем это дальше, как только закончим MainMenu3D.
Шаг 34: Обработка вступительной анимации
Если вы изучите, как работает главное меню по ссылке предварительного просмотра вверху страницы, вы увидите последовательность операций. Границы меню исчезают и открываются. После открытия кнопки начинают показывать снизу вверх. Все мигает и играет звук. Для начала необходимо подготовить вступительную анимацию перед ее воспроизведением Добавьте код ниже после метода setMenuEffect ():
защищенная функция prepareIntro (): void { // добавить эффект искажения позже _topNav.y = 50; // позиционируем 50 единиц вверх от центра _bottomNav.y = -50; // 50 единиц вниз от центра _topNav.interfaceLayer.alpha = _bottomNav.interfaceLayer.alpha = 0; // устанавливаем альфа в 0, применяя его к каждому свойству interfaceLayer UIComponent3D (ViewportLayer) для каждого (кнопка var: Button3D в _buttonArray) button.visible = false; }
Здесь мы добавим контроль для активации эффекта искажения, который вы создадите позже. Приведенный выше код размещает 2 границы близко к центру, чтобы они могли анимироваться наружу в форме открытия. Их альфа установлены на 0, поэтому они могут медленно появляться при запуске вступления. После этого все кнопки становятся невидимыми, поэтому они могут появляться последовательно 1 к 1 после завершения открытия границ.
Добавьте код ниже, следующий. Это позаботится об игре вступления и предоставит внешний доступ к нему:
публичная функция startIntro (): void { prepareIntro (); var sound: Sound = CustomLoader.getInstance () .getSound ('menuExpand'); TweenMax.to (_topNav.interfaceLayer, .4, {alpha: 1, задержка: .5, onStart: sound.play, onStartParams: [0,0, новый SoundTransform (1)], перезапись: false}); TweenMax.to (_bottomNav.interfaceLayer, .4, {alpha: 1, задержка: .5, перезапись: false}); TweenMax.to (_topNav, .5, {y: 354, задержка: .75, замедление: Expo.easeInOut, перезапись: false}); // 0 TweenMax.to (_bottomNav, .5, {y: -350, задержка: .75, замедление: Expo.easeInOut, перезапись: ложь, onComplete: initializeButtons}); // 0 }
Этот метод вызывает prepareIntro (), чтобы получить все на своем месте перед запуском анимации. Локальной переменной звука типа Sound присваивается ссылка на звуковой эффект с именем ‘menuExpand’, сохраненный в экземпляре CustomLoader. Затем TweenMax используется для постепенного исчезновения альфа-свойства 2 границ. Эта анимация имеет длительность 0,4 секунды и коэффициент задержки 0,5 секунды. Звук вызывается для воспроизведения при запуске, и анимация настроена так, чтобы не перезаписываться. Еще один вызов TweenMax назначен для фактического перемещения 2 границ, на этот раз с задержкой 0,75 секунды. .25 секунд после начала постепенного изменения, 2 границы анимируются для открытия. 2 границы открываются через 0,5 секунды, а когда они заканчиваются, вызывает метод initializeButtons ().
Добавьте код ниже:
защищенная функция initializeButtons (): void { для каждого (кнопка var: Button3D в _buttonArray) button.activate (); // убедитесь, что кнопки активны для (var i: uint = 0; i <_buttonArray.length; i ++) { TweenMax.delayedCall (((_buttonArray.length - 1) - i) * .07, showButtons, [_buttonArray [i]]); } }
Вот как 4 кнопки активируются и затем последовательно добавляются в меню. Он рассчитывает назад от количества кнопок, задержанных на 0,07 секунды. На каждой итерации вызывается showButtons (), передавая значение _buttonArray для текущей итерации. Ниже приведен последний метод, который завершает вводную анимацию:
защищенная функция showButtons ($ button: Button3D): void { $ button.visible = true; $ button.onObjectOver (новый InteractiveScene3DEvent (InteractiveScene3DEvent.OBJECT_OVER)); // симулируем наведение мыши на кнопку $ button.z = Button3D.OUT_POSITION; }
Как только это вызвано, кнопка, переданная как параметр, обрабатывается. Сначала она показывает кнопку, а затем запускает ее метод onObjectOver () для имитации события мыши. Сразу после этого она помещает кнопку в положение мыши по умолчанию.
Шаг 35: Обработка событий мыши
Внутри MainMenu3D кнопки будут обрабатываться по их названию, чтобы идентифицировать, какая кнопка была нажата, и отправлять соответствующее событие, которое нужно вызвать. Метод onButtonClick () отправит событие в MainMenu3D, содержащий родительский элемент, либо UserInterface3D, либо класс Tester, который мы используем в данный момент. Добавьте код ниже:
защищенная функция onButtonClick (e: InteractiveScene3DEvent): пусто { переключатель (e.target.name) { case 'start game': dispatchEvent (новое событие (START_GAME_CLICKED)); перемена; case 'settings': dispatchEvent (новое событие (SETTINGS_CLICKED)); перемена; case 'about': dispatchEvent (new Event (ABOUT_CLICKED)); перемена; case 'exit': dispatchEvent (new Event (EXIT_CLICKED)); перемена; } startExit (); // запускаем анимацию выхода }
Остальная анимация для кнопки выполняется самой кнопкой. Помните, мы установили этот метод так, чтобы он вызывался методом onObjectClick () каждой кнопки. Этот метод заботится обо всех эффектах анимации кнопок перед отправкой этого события вверх. После отправки соответствующего события меню информируется о выходе. Затем добавьте приведенный ниже код для метода onButtonRelease ():
защищенная функция onButtonRelease (e: InteractiveScene3DEvent): пусто { для каждого (кнопка var: Button3D в _buttonArray) { button.deActivate (); } }
Это самый простой метод для MainMenu3D, его единственная цель — убедиться, что при нажатии кнопки пользователь, независимо от того, как быстро он пытается, не сможет нажать другую кнопку и, возможно, вызвать что-то нежелательное. Вернитесь к методу onObjectClick () Button3D, чтобы увидеть, как это происходит.
Шаг 36: Обработка анимации выхода
Как только пользователь решит, что делать, либо отредактируйте настройки, играйте в игру, что угодно, Mainmenu3D начнет выходить и сообщит Tester или UserInterface3D, когда это будет сделано. Обратите внимание, что этот метод объявлен как public, соответствующий его аналогу startIntro (). UserInterface3D не нужно будет вызывать этот метод, поскольку он обрабатывается внутри. Добавьте код ниже:
публичная функция startExit (): void { // добавить эффект деактивации позже для (var i: uint = 0; i <_buttonArray.length; i ++) { TweenMax.delayedCall ((i) * .07, hideButtons, [_buttonArray [i]]); } }
Здесь мы добавим контроль, чтобы отключить эффект искажения, упомянутый ранее. Здесь кнопки скрыты от просмотра по очереди. Противоположно тому, как они появились в методе initializeButtons (). Добавьте метод hideButtons () следующим образом:
защищенная функция hideButtons ($ button: Button3D): void { $ button.onObjectOver (новый InteractiveScene3DEvent (InteractiveScene3DEvent.OBJECT_OVER)); $ button.z = Button3D.OUT_POSITION; TweenMax.delayedCall (.1, hideObject, [$ button]); if ($ button == _buttonArray [_buttonArray.length - 1]) // когда все кнопки скрыты { closeNav (); } }
Этот метод заставляет кнопки мигать одна за другой, а затем прятаться по порядку до того, как 2 границы анимации закрываются. Сначала он имитирует эффект мыши. Применяется еще один метод delayedCall (), чтобы кнопка оставалась достаточно длинной, чтобы завершить действие над кнопкой до ее удаления из видимости. После этого он проверяет, является ли обрабатываемая кнопка последней кнопкой в списке кнопок, и если это так, вызывает метод closeNav (). Добавьте следующие 2 метода:
защищенная функция hideObject ($ object: DisplayObject3D): void {$ object.visible = false; } // устанавливает кнопку невидимой после того, как кнопка имитирует событие над кнопкой защищенная функция closeNav (): void { var sound: Sound = CustomLoader.getInstance () .getSound ('menuCollapse'); TweenMax.to (_topNav.interfaceLayer, .2, {alpha: 0, задержка: .4, перезапись: false}); TweenMax.to (_bottomNav.interfaceLayer, .2, {alpha: 0, delay: .4, перезапись: false, onComplete: dispatchEvent, onCompleteParams: [новое событие (EXIT_COMPLETE)]}); TweenMax.to (_topNav, .5, {y: 50, onStart: sound.play, ease: Expo.easeInOut, overwrite: false}); TweenMax.to (_bottomNav, .5, {y: -50, ease: Expo.easeInOut, overwrite: false}); }
Как только все кнопки станут невидимыми, 2 границы начнут закрываться. Первые 2 вызова TweenMax заботятся о затухании верхней и нижней границ. Затухание занимает 0,2 секунды с задержкой 0,4 секунды. Конец замирания отправляет событие EXIT_COMPLETE. Для второго набора вызовов TweenMax границы анимируются внутрь закрывающим образом. Это займет 0,5 секунды, использует Expo.easeInOut для простоты и не имеет никакой задержки. Этот вызов также воспроизводит звук menuCollapse для звукового эффекта закрытия. И мы закончили с MainMenu3D! Хорошо, сохраните и будьте готовы к тестированию.
Шаг 37: Тестирование вехи MainMenu3D
Вернитесь к методу init () класса Tester. Закомментируйте вызов addButton () и добавьте вызов addMainMenu () под ним. Скопируйте метод ниже после метода init ():
приватная функция addMainMenu (): void { var mm: MainMenu3D = новый MainMenu3D («меню», область просмотра); mm.addEventListener (MainMenu3D.START_GAME_CLICKED, navigateTo); mm.addEventListener (MainMenu3D.SETTINGS_CLICKED, navigateTo); mm.addEventListener (MainMenu3D.ABOUT_CLICKED, navigateTo); mm.addEventListener (MainMenu3D.EXIT_CLICKED, navigateTo); mm.addEventListener (MainMenu3D.EXIT_COMPLETE, onMenuExitComplete); scene.addChild (mm); mm.startIntro (); }
Здесь создается экземпляр MainMenu3D с передачей имени ‘menu’ для имени и окна просмотра для его свойства _viewport. Затем прослушиватели назначаются для всех событий, которые отправляет экземпляр MainMenu3D. После добавления его в сцену нам нужно вызвать открытый метод MainMenu3D startIntro () для его загрузки. Давайте добавим соответствующие методы для слушателей перед тестированием. Добавьте код ниже после метода addMainMenu ():
приватная функция navigateTo (e: Event): void { переключатель (электронный тип) { case MainMenu3D.START_GAME_CLICKED: трассировка («загрузить игру и играть»); перемена; case MainMenu3D.SETTINGS_CLICKED: трассировка («меню настроек загрузки»); перемена; case MainMenu3D.ABOUT_CLICKED: трассировка («загрузить о меню»); перемена; case MainMenu3D.EXIT_CLICKED: трассировка («выход из приложения»); перемена; } } приватная функция onMenuExitComplete (e: Event): void { MainMenu3D (e.target) .startIntro (); }
Теперь запустите приложение.Нажмите здесь, чтобы увидеть результат:
После нажатия любой из 4 кнопок экземпляр MainMenu3D отправляет событие и завершается. Вы должны увидеть распечатки того, что сработала кнопка. Здесь мы просто загружаем меню снова, когда получено событие MainMenu3D.EXIT_COMPLETE. Опять же, кнопки могут мигать немного быстро, чтобы их заметили все, но они должны замедлиться, как только мы начнем добавлять эффекты. Поиграйте с ним немного, чтобы лучше с ним познакомиться. Мы собираемся расширить этот класс для подменю AboutMenu3D и SettingsMenu3D позже. Теперь давайте поработаем над DistortionEffect3D, прежде чем перейти к более высоким основаниям.
Вывод
Спасибо за чтение до этого момента! Присоединяйтесь ко мне снова для второй и заключительной части, где мы закончим наш интерфейс.