voliuf.narod.ru

главная

друзья

помощь сайту

Flash MX Studio

Бесплатные учебники по темам

Партнерская программа

1.Представление сайта

2.Форматирование текста

3.Рисование API

4.Компоненты

5.Движемся дальше

6.Интерфейсы AсtionScript

7.Обнаружение коллизий

8.Математика и физика Flash

9.Анимация и интерактивность Drawing API

10.Реализация 3D-графики с помощью рисования API

11.Изучение SphereCage

12.Сайты с мультимедийным содержимым

13.Видеоданные

14.Аудио

15.Интеграция динамических данных

16.Динамический Flash: PHP

17.XML

18.Flash, ColdFusion и Remoting


 


Flash MX Studio
1.Представление сайта
Движение
Внимание! Для работы с этой лекцией необходимы учебные файлы, которые Вы можете загрузить  здесь.

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

 

Некоторым читателям эти принципы уже могут быть знакомы, однако мы также будем изучать новые возможности Flash MX, позволяющие обеспечивать движение наиболее простыми и эффективными методами, нежели это было прежде. Чтобы продемонстрировать гибкость Flash, рассмотрим несколько различных типов движения, которое вы, возможно, захотели бы добавить в свои проекты, а также способы его применения. Иногда мы будем использовать ActionScript для получения следующих типов движения:

 
  • уменьшение: уменьшение скорости движения;
  • свинг: добавление ускорения и колебания движению;
  • покадровое движение: достижение движения с использованием кадров.
 

Сначала рассмотрим, как можно использовать эти типы движения для перемещения объектов со следом от движения по осям X и Y. Также обратим внимание на то, как применить это движение к другим параметрам, таким как размер объекта.

 

Помимо самого движения, мы рассмотрим различные способы применения движения с помощью ActionScript: как вызывать движение щелчком мыши и как лучше поддерживать движение, т.е. как начать его и как завершить.

 

Наконец, остановимся на учебном примере, содержащем несколько картинок, появляющихся в области просмотра при щелчке на кнопке. Подходы, описанные в упражнении, включают в себя создание маски с помощью ActionScript, а также динамическое применение кнопки.

 

Итак, шутки в сторону! Начнем с рассмотрения покадрового движения.

 

Уменьшение скорости движения

Первым типом движения, о котором мы бы хотели рассказать, является уменьшение скорости движения: объект сначала движется довольно быстро и постепенно замедляется, пока, наконец, не останавливается достигнув цели. Этот тип движения, вероятно, наиболее прост в реализации - нужно выяснить, как далеко находится объект от цели и затем переместить объект к цели, разделив дистанцию на части. Итак, если объект находится на расстоянии 100 пикселей от конечной точки, мы можем переместить его на половину этого расстояния, после чего он будет в 50 пикселях от цели, далее - в 25, затем в 12,5 и так далее. Движение при этом будет плавным; ведь мы привыкли наблюдать постепенное замедление объектов, а не прерывистые движения.

 

На рисунке ниже данное движение показано в действии, причем каждая линия представляет собой кадр перемещения объекта на 200 пикселей.

 

 


 

 

С каждым кадром расстояние объекта до цели сокращается наполовину. В кадре 1 объект перемещается на 100 пикселей, в кадре 2 - на 50 пикселей, в кадре 3 - на 25 пикселей, затем на 12,5 пикселей, затем на 6,25, затем на 3,125 и так далее.

 

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

 

Создание клипа с уменьшением скорости движения

  1. Откройте новый файл Flash со значением разрешения по умолчанию (550x400). В Property Inspector установите цвет фона на белый и частоту смены кадров на значение 31 кадр в секунду. (Мы будем использовать эти настройки всегда при создании файла Flash в этой части книги.)
  2. Нарисуйте черный круг, преобразуйте его в символ клипа (F8) и затем присвойте клипу имя.
  3. Откройте Property Inspector и присвойте инстансу* клипа имя 'ball_mc'.

    Мы используем суффикс '_mc' в имени согласно установленным Macromedia преобразованиям имен. Использование этого правила имеет два преимущества: во-первых, это помогает отличать разные типы объектов в коде, а во-вторых, таким образом обеспечивается появление подсказки в коде нужного типа при вводе кода в среде разработки.

     

    Мы проделали основные действия. Теперь углубимся в процесс работы.

     
  4. Так как в большинстве случаев лучше содержать действия в отдельном слое от остального содержимого, добавьте новый слой под текущим слоем. Лучше всегда давать имена всем используемым слоям. Наши слои мы назвали просто circle и script.

     


     

     
  5. Выберите первый кадр первого слоя и откройте панель Actions. Щелкните на маленьком белом значке параметров в правом углу панели и убедитесь, что отмечен параметр Expert Mode. Лучшим способом быстрого ознакомления с кодом является его ввод, это может быть неприятно, но полезно.
  6. Итак, перейдем к коду. Нам нужно применить событие к нашему фильму, которое в каждом кадре проверяет, где находится указатель мыши, и затем перемещается за этим указателем. Во Flash 5 это проще всего было бы сделать выделением фильма и прикреплением к нему события onClipEvent (enterFrame).

    Благодаря новой объектной модели, во Flash MX этого можно больше не делать. Мы можем динамически прикреплять события clipEvents к фильмам, что позволит всему или почти всему коду находиться в одном месте, а также позволит манипулировать этими событиями во время выполнения, например, включать и выключать их или изменять какую-либо функциональность.

     

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

     

    Введите следующий код в кадр 1 слоя script:

     
    ball_mc.onEnterFrame = function() {
      this._x += (this._parent._xmouse-this._x) /4 ;
      this._y += (this._parent._ymouse-this._y) /4;
    };

               

     

     
    Этот код сначала создает функцию, которая присваивается управляющему элементу onEnterFrame фильма 'ball_mc'. Код этой функции сначала выясняет, насколько далеко находится объект от указателя мыши, и затем добавляет четверть этого расстояния до позиции фильма. Если вам нужно было бы написать этот код, так сказать, своими словами, то получилось бы следующее: "вычислить разницу между позициями указателя по осям X и Y, затем увеличить позицию X на четверть этого значения".
  7. Сохраните ваш фильм в файле ball motion_01.fla и протестируйте его.

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

     
 

Добавление переменной скорости движения

Чтобы было легче менять скорость движения объекта в вашем фильме, добавьте переменную скорости (чем меньше будет значение, тем быстрее будет двигаться объект).

 
  1. Используя те же предварительные действия, что и в предыдущих примерах, с помощью панели Actions добавьте следующий код в кадр 1 вашего слоя script:
    var speed = 4;

    ball_mc.onEnterFrame = function() {
      this._x += (this._parent._xmouse-this._x)/speed;
      this._y += (this._parent._ymouse-this._y)/speed;
    };

               

    Обратите внимание на то, что внутри функции onEnterFrame слово 'this' ссылается на фильм, которые вы назвали ball_mc, поэтому даже при обращении к переменной скорости из функции нужно вводить this._parent.speed, чтобы оказаться на том уровне, на котором находится фильм. Уровень _root level является уровнем, на котором определена переменная speed.

     
  2. Сохраните ваш фильм как ball motion_02_speed var.fla и запустите его. Движение происходит таким же образом, однако теперь легче внести изменение в код.
 

Инициализация движения щелчком мыши

Теперь мы значительно изменим код, чтобы фильм перемещался в любое место, где пользователь щелкнет мышью. Аналогично тому, как мы присваивали функцию onEnterFrame фильму, мы можем присвоить ему функцию onMouseDown. Эта функция будет выполняться при каждом нажатии кнопки мыши в любом месте на главном фильме. Итак, когда пользователь щелкает мышью, нужно сначала установить позиции целей фильма на местоположение щелчка, а затем выполнить функцию onEnterFrame для перемещения на эту позицию:

 
  1. Используя настройки кадра, примененные в предыдущих примерах, воспользуйтесь панелью Actions для добавления следующего кода в кадр 1 слоя script:
    var speed = 4;
    // set up target variables
    ball_mc.targetX = 0
    ball_mc.targetY = 0

    ball_mc.moveToMouse = function() {
      this._x += (targetX-this._x)/speed;
      this._y += (targetY-this._y)/speed;
    };

    triggerMotion = function() {
      // reset target variables on click
      targetX = _xmouse;
      targetY = _ymouse;
      // set the movieclip in motion
      this.onEnterFrame = this.moveToMouse;
    }
    ball_mc.onMouseDown = triggerMotion;

               

    Можно видеть, что этот ActionScript кардинальным образом отличается от предыдущего ActionScript. Если раньше мы присоединяли функцию непосредственно к управляющему элементу onEnterFrame, то на этот раз мы сначала определяем функцию moveToMouse, и при щелчке мышью выражение this.onEnterFrame указывает на эту функцию и вызывает ее в каждом кадре. Функция сама по себе работает так же, как и прежде, за исключением того, что перемещение происходит не на позицию указателя мыши, а на значения переменных targetX и targetY, являющихся переменными местоположения указателя мыши, значения которых определяются при каждом щелчке мышью пользователем.

     

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

     
  2. Сохраните ваш фильм в файле ball motion_03_click to move.fla и запустите его.

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

     
 

Добавление следа от движения объекта

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

 

Дубликат находится по умолчанию на той же позиции, что и исходный фильм. На самом деле, дубликат имеет все те же параметры, что и исходный фильм, такие как alpha, xscale, yscale и т.д., однако у него нет функций onEnterFrame или переменных, которые может содержать исходный фильм. Это одно из отличий от Flash 5, в котором если создавался дубликат фильма с присвоенным событием clipEvent, также создавался дубликат этого события, которое происходило и на дубликате фильма. Мы располагаем каждый дубликат на один уровень выше предыдущего, посредством добавления переменной глубины для '_root', значение которой увеличивается с каждым кадром.

 

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

 
  1. Используйте те же настройки, как и в предыдущих примерах, и добавьте следующий ActionScript в ваш фильм:
    var speed = 4;

    ball_mc.moveToMouse = function() {
      this._x += (this.targetX-this._x)/this._parent.speed;
      this._y += (this.targetY-this._y)/this._parent.speed;
      this.duplicateMovieClip("dupe"+this._parent.depth,
        this._parent.depth++);
    };
    ball_mc.onMouseDown = function() {
      this.targetX = this._parent._xmouse;
      this.targetY = this._parent._ymouse;
      this.onEnterFrame = this.moveToMouse;
    };

               
  2. Сохраните фильм в файле ball motion_04_click for trail.fla. Если теперь запустить фильм, вы сразу увидите, как работает это замедление, и заметите, что это очень похоже на то, что было изображено на диаграмме.

     


     

     

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

     
 

Исчезновение следа

Чтобы не забивать фильм слишком большим количеством дубликатов одного и того же объекта, мы можем присвоить каждому дубликату свою собственную функцию enterFrame, которая будет обеспечивать уменьшение дубликатов с каждым кадром и затем удалять их по достижении определенного размера.

 

Так как мы собираемся работать с каждым из дубликатов, имеет смысл присвоить объекту ball_mc его собственную функцию duplicate(). Приведем код с выделенными вводимыми новыми частями:

 
var speed = 4;

ball_mc.moveToMouse = function() {
  this._x += (this.targetX-this._x)/this._parent.speed;
  this._y += (this.targetY-this._y)/this._parent.speed;
  this.duplicate() ;
};
ball_mc.duplicate = function() {
  var dupe = this.duplicateMovieClip("dupe"+this._parent.depth,
  this._parent.depth++);
  dupe.onEnterFrame = this._parent.diminish
};
ball_mc.onMouseDown = function() {
  this.targetX = this._parent._xmouse;
  this.targetY = this._parent._ymouse;
  this.onEnterFrame = this.moveToMouse;
};
  function diminish(){
    // reduce scale gradually
    this._xscale = this._yscale-=2;
    //remove movieclip when scale goes below zero
    if (this._xscale <= 0) {
      this.removeMovieClip();
    }
  }

           

Итак, мы добавили вызов функции duplicate() и значительно изменили вызов duplicateMovieClip, вынеся вперед var dupe=. Несмотря на то, что в словаре ActionScript указано, что duplicateMovieClip не возвращает никакого значения, на самом деле, возвращается ссылка на созданный фильм.

 

Здесь мы брали это значение и помещали его в переменную dupe. Мы объявили переменную с помощью выражения var так, что это значение существует только во время выполнения функции, и по окончании ее выполнения оно исчезает за ненадобностью.

 

Теперь мы можем использовать dupe для ссылки на наш новый дубликат фильма и для присвоения ему функции onEnterFrame, функции diminish, определенной в _root. В функции diminish мы уменьшаем инкременты xscale и yscale с каждым кадром, и когда они достигнут нуля, фильм удаляется.

 

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

 

 


 

 

Повышение эффективности

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

 

Итак, по мере продолжения фильма, нужно проверять, находится ли он в своей конечной точке, и, если это так, завершать его. Казалось бы, легко определить, является ли позиция фильма x равной позиции фильма y, и т.д. На самом деле, в случае с данным замедлением скорости, фильм никогда не достигает своей конечной цели, а лишь бесконечно приближается к ней до тех пор, пока расстояние не станет пренебрежимо малым.

 

Если вернуться к исходному примеру объекта, двигающегося от 0 до 200, с разбиением каждого отрезка дистанции на две части, то для каждого кадра будут следующие позиции: 100, 150, 175, 187,5, 193,75, 196,875, 198,4375, 199,21875, 199,609375, 199,8046875. Это называется парадоксом Зено, который заключается в том, что если объект всегда перемещается на половину предыдущей дистанции, то он никогда не достигнет цели, все приближаясь и приближаясь к ней. Так как невозможно разделить на две части один пиксель, картинка будет казаться неподвижной, однако ActionScript этого не учитывает. Вместо того чтобы проверять, находится ли фильм в своем конечном положении, мы будем проверять, находится ли он рядом со своей целью, и меньше ли заданного расстояние между объектом и его целью. При подходе объекта к конечной точке можно остановить его, удалив управляющий элемент onEnterFrame.

 

Начав с нашего предыдущего кода, мы добавим новую функцию checkDistance для проверки того, является ли расстояние меньшим, нежели определенное число. Фильм затем перейдет в свое конечное положение, и функция, присвоенная onEnterFrame, будет удалена. Добавьте следующий код после уже имеющейся программы:

 
ball_mc.checkDistance = function() {
  // check movieclip is within 0.2 pixels of target
  if (Math.abs(this.targetX-this._x)<0.2
    && Math.abs(this.targetY-this._y)<0.2) {
    this._x = this.targetX;
    this._y = this.targetY;
    delete this.onEnterFrame;
  }
};

           

Прежде всего, у нас есть условное выражение, проверяющее, находится ли фильм внутри отрезка длиной 0,2 пикселя от цели. В коде this.targetX-this._x представлено расстояние от фильма до цели по оси X, и мы используем Math.abs для преобразования этого значения в положительное, так как безразлично, справа или слева находится фильм от конечной точки, т.е. между -0,2 и +0,2. Наконец, в функции moveToMouse мы добавляем вызов функции checkDistance:

 
ball_mc.moveToMouse = function() {
  this._x += (this.targetX-this._x)/this._parent.speed;
  this._y += (this.targetY-this._y)/this._parent.speed;
  this.duplicate();
  this.checkDistance();
};

           

Выполнение этого кода приведет к тому же результату, что и в случае с предыдущим файлом. Однако если выбрать команду Debug>List Variables в режиме Test Movie после окончания фильма, вы увидите, что дубликаты отсутствуют, и фильм ball_mc не имеет функции onEnterFrame. По большому счету, в нашем фильме ничего не происходит - он просто находится в ожидании щелчка мыши, чтобы запуститься вновь.

 

Давайте теперь перейдем к рассмотрению того, как можно создать постоянное, основанное на времени, движение.

 

Покадровое движение

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

 

 


 

 

Расстояние, на которое перемещается объект, одинаково во всех кадрах. Пройденное расстояние равно всему расстоянию, деленному на число кадров, в данном случае, 200 пикселей делится на 5 кадров и получается 40 пикселей на каждый кадр.

 

Постоянная скорость

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

 
  1. Проделайте те же шаги, что и в предыдущем примере, чтобы приготовиться к добавлению ActionScript в панель Actions.
  2. Итак, перейдем к программе. Нам нужно присвоить действие нашему фильму, с помощью которого в каждом кадре будет выявляться местоположение указателя мыши, после чего фильм будет перемещаться в эту точку. Во Flash 5 это можно было бы легко сделать с помощью выделения фильма и присвоения ему onClipEvent (enterFrame).
  3. Прежде всего, мы введем переменную для хранения числа кадров движения. Затем мы установим функцию onMouseDown для ball_mc. Эта функция будет вычислять общее расстояние по осям x и y и затем делить это число на значение переменной кадров для выяснения расстояния, на которое будет перемещаться фильм в каждом кадре.
  4. Мы также введем переменную-счетчик frameNum, которая будет использоваться для определения того, на какое расстояние переместился фильм - мы будем прибавлять к ее значению единицу в каждом кадре фильма, и когда она будет равна значению переменной кадров, движение будет прекращаться.
    this.frames = 30;

    ball_mc.onMouseDown = function() {
      this.frameNum = 0;
      // calculate how far to move each frame on the x and у axes
      this.xStep = (this._parent._xmouse-this._x) /this._parent.frames ;
      this.yStep = (this._parent._ymouse-this._y) /this._parent.frames;
      this.onEnterFrame = moveToMouse;
    };

               
  5. Далее нам нужно будет написать функцию moveToMouse, которая будет сначала добавлять значения xStep и yStep, добавлять дубликат и затем проверять, достиг ли он своей конечной точки:
    moveToMouse = function () {
      // add the step value each frame
      this._x += this.xStep;
      this._y += this.yStep;
      this.duplicate();
      this.checkTime();
    };

               
  6. Функции дубликата и уменьшения идентичны тем, которые мы только что использовали.
  7. Последним добавлением в наш код будет функция checkTime, прибавляющая единицу к значению переменной frameNum и затем прекращающая движение по достижении конечной точки, т.е. числа кадров, указанного нами в начале:
    ball_mc.checkTime = function() {
      this.frameNum++;
      if (this.frameNum == this._parent.frames) {
        delete this.onEnterFrame;
      }
    };

               
  8. Сохраните фильм в файле frame based motion.fla и запустите его. При выполнении этого кода вы увидите, что дубликаты создаются непрерывно, и фильм непосредственно достигает конечной точки.

     


     

     

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

     
 

 

 

Колебательное движение

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

 

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

 

 


 

 

Скорость объекта увеличивается в пропорции с расстоянием, на котором он находится от конечной точки. Из рисунка видно, что сначала он стремительно ускоряется, проходит конечную точку и затем возвращается обратно. Амплитуда его колебаний около цели медленно уменьшается.

 

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

 
  1. Деление расстояния от конечной точки, которое прибавляется к скорости.
  2. Деление, на которое умножается скорость для ее уменьшения.
 

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

 
  1. Это упражнение будет использовать те же основные установки, какие были настроены ранее с фильмом, размещенным на рабочем месте с именем ball_mc и отдельным слоем для кода. Мы также можем использовать некоторый код, который был применен ранее (функции, проверяющие расстояние, создающие следы и обрабатывающие событие mouseDown), но он представляет собой лишь само движение, и нам необходимо изменить его.
    ball_mc.checkDistance = function() {
      if (Math.abs(this.targetX-this._x)<0.2
       && Math.abs(this.targetY-this._y)<0.2) {
        this._x = this.targetX;
        this._y = this.targetY;
        delete this.onEnterFrame;
      }
    };

    ball_mc.duplicate = function() {
      var dupe = this.duplicateMovieClip
        ("dupe"+this._parent.depth,
            this._parent.depth++);
      dupe.onEnterFrame = this._parent.diminish
    };

    function diminish(){
      // reduce scale gradually
      this._xscale = this._yscale-=2;
      //remove movieclip when scale goes below zero
      if (this._xscale <= 0) {
        this.removeMovieClip();
      }
    }

    ball_mc.onMouseDown = function() {
      this.targetХ = this._parent._xmouse;
      this.targetY = this._parent._ymouse;
      this.onEnterFrame = this.moveToMouse;
    };
               
  2. Единственное, что нам нужно добавить, это функция moveToMouse, переменные скорости и т.д. Сначала необходимо определить два наших параметра, которые мы будем называть acceleration (ускорение) и friction (колебание). Установим для них значения 12 и 0,8, несмотря на то, что у нас будет возможность изменить их позднее для достижения различных эффектов. Добавьте эти две строки перед определением функции, в верхней части кода:
    var acceleration = 12;
    var friction = 0.8;

               

    Итак, acceleration будет значением, на которое мы делим расстояние перед добавлением его к скорости нашего фильма, а friction будет являться значением, которое умножается на скорость каждого кадра по порядку для уменьшения быстроты движения.

     

    Мы проработаем код движения по оси x перед добавлением его в функцию moveToMouse.

     
  3. Прежде всего, мы создадим временную переменную для хранения расстояния между нашим фильмом и конечной точкой. Следующий код предназначен для функции moveToMouse.
    var xdif=this.targetX-this._x;
               
  4. Затем мы добавим результат деления этого значения к нашему значению xspeed (переменная, представляющая скорость фильма по оси x):
    this.xspeed+=xdif/this._parent.acceleration;
               
  5. Затем умножаем переменную speed на переменную friction для уменьшения скорости. Если не делать этого, наш фильм будет колебаться около своей конечной точки, не приближаясь к ней. Это умножение означает, что амплитуда уменьшается с каждым разом. Если убрать эту строку из исходного кода нашего окончательного результата, фильм не остановится на своей конечной точке, а будет двигаться вперед-назад на одно и то же расстояние.
    this.xspeed*=this._parent.friction;
               
  6. Наконец, обновляем фильм, добавляя значение его скорости к положению на оси x:
    this._x+=this.xspeed
               

    Теперь мы объединяем все это в одну функцию moveToMouse, добавляя также вызовы дубликата и checkDistance. Ниже приведен полный код программы, как для оси x, так и для оси y:

     
    ball_mc.moveToMouse = function() {

      // calculate difference on x and у axes
      var xdif = this.targetX-this._x;
      var ydif = this.targetY-this._y;

      // increment speed values
      this.xspeed += xdif/this._parent.acceleration;
      this.yspeed += ydif/this._parent.acceleration;

      // dampen speed values
      this.xspeed *= this._parent.friction;
      this.yspeed *= this._parent.friction;

      // add speed values to x and у properties
      this._x += this.xspeed;
      this._y += this.yspeed;

      // create duplicate
      this.duplicate();
      // check if the movieclip has reached its target
      this.checkDistance();
    };

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

 


 

 

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

 

Вообще говоря, чем ниже значение acceleration, тем быстрее будет сначала двигаться фильм, и чем ближе к единице значение friction, тем больше фильм будет колебаться вперед и назад. Некоторые значения могут сделать этот пример очень похожим на случай с уменьшением скорости, рассмотренный нами в первую очередь. Например, попробуйте ввести значения acceleration = 17; и friction = 0.4; и сохраните ваш фильм в файле swing02.fla. Разница в том, что у нас есть переменная, сохраняющаяся во время прохождения кадров, и фильм не изменяет моментально направление своего движения, как это было в случае с исходным уменьшением скорости движения, или движением по кадрам, и поэтому эти изменения происходят плавней.

 

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

 

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

 
ball_mc.checkDistance = function() {
  // check that distance is within range
  if (Math.abs(this.targetX-this._x)<0.2
    && Math.abs (this. targetY-this ._y) <0 .2) {

    // check that speed is nearly zero
    if(Math.abs(this.xspeed)<0.2 && Math.abs(this.yspeed) <(0.2) {
      this._x = this.targetX;
      this._y = this.targetY;
      delete this.onEnterFrame;
    }
  }
};

           

Приведенный выше сценарий, содержащийся в swing3.fla, теперь защищен от любых непредвиденных обстоятельств.

 

 


 

 

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

 

Если вам интересны способы создания других типов движения, рекомендуем вам обратить внимание на уравнения замедления на сайте www.robertpenner.com. Используя эти уравнения, вы можете указывать количество кадров, которое необходимо для определенной продолжительности движения, и фильм будет замедлять свое движение от точки A до точки B. В дополнение к этому, вы можете изучить применение этих уравнений на www.gizma.com/easing. Если вам интересны эти уравнения, Chris Andrade из www.fifthrotation.com опубликовал документ, описывающий их вывод, по адресу http://www.fifthrotation.com/u2/parabolic_ease.zip.

 

Изменение размеров в движении

До этого момента мы рассматривали различные типы замедления применительно к движению по осям x и y, однако использование этого типа движения не ограничивается лишь только этими параметрами. Можно переходить от одного значения к другому и создавать движение, основанное на изменении размеров объектов.

 

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

 
  1. Создайте файл с фильмом таким же образом, как и в предыдущих примерах, с именем фильма ball_mc, но на этот раз расположите фильм, указав значения X = 275 и Y = 200 (около середины рабочего места).

     


     

     
  2. Мы начнем с определения функции mouseDown. Сложим координаты X и Y указателя мыши, затем умножим результат на два и используем его для определения конечного размера нашего фильма. Если пользователь щелкнет на левом верхнем углу, фильм примет размер, равный нулю, а если щелчок будет в правом нижнем углу, тогда размер станет равным 1900, т.е. (550+400)*2.
    ball_mc.onMouseDown=function(){
      this.targetScale=(this._parent._xmouse+this._parent._ymouse)*2
      this.onEnterFrame=this.scaleMe
    }
     
             

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

     
  3. Теперь нам нужно определить функцию scaleMe, которая будет изменять размер фильма с текущего до конечного. Это делается с помощью достижения определенной точки на осях x и y, аналогичного рассмотренному ранее. Единственная разница заключается в том, что мы будем изменять параметры _xscale и _yscale вместо _x и _y. Так как мы хотим приравнять _xscale к _yscale, мы можем проводить все вычисления с использованием _xscale и затем установить _yscale на такое же значение:
    this.acceleration = 12;
    this. friction = 0.8;
    ball_mc.scaleMe = function() {
      var scaleDiff = this.targetScale-this._xscale;
      this.scaleSpeed += scaleDiff/this._parent.acceleration;
      this.scaleSpeed *= this._parent.friction;
      this._yscale = this._xscale += this.scaleSpeed;
      this.checkScale();
    };

               

    Первые три строки функции такие же, как и ранее - они вычисляют разницу между текущим размером и конечным размером, и рассчитывают, на сколько увеличивается scaleSpeed. Затем переменная скорости уменьшается посредством умножения на константу friction.

     

    В следующей строке мы производим два действия, эквивалентные следующим строкам.

     
    this._xscale += this.scaleSpeed;
    this._yscale = this._xscale;

               

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

     
  4. Сохраните ваш фильм в файле scale.fla и запустите его - теперь объект будет принимать различные размеры, в зависимости от того, на каком месте вы щелкните мышью.
  5. Последнее, что нужно сделать, это добавить функцию checkScale. Она более или менее похожа на функцию checkDistance, с которой мы имели дело ранее, и предназначена для проверки того, что размер фильма более или менее близок к конечному размеру, и что его скорость почти равна нулю:
    ball_mc.checkScale = function() {
      if (Math.abs(this.targetScale-this._xscale)<0.2) {
        if (Math.abs(this.scaleSpeed)<0.2) {
          this._xscale = this._yscale=this.targetScale;
          delete this.onEnterFrame;
        }
      }
    };

               

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

     
 

Управление движением

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

 

Было бы гораздо лучше брать любой определенный фильм и создавать myMovieClip.slideTo(100,200), чтобы фильм мог перемещаться к этой точке и останавливаться, без надобности присваивать фильму вручную управляющий элемент clipEvent или функцию для проверки достижения конечной точки, и т.д.

 

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

 

Скольжение

  1. Откройте новый фильм и разместите на рабочем месте инстанс ball_mc.
  2. Первое, что мы сделаем на отдельном слое сценариев, это добавим вызов функции slideTo, которая будет выполняться каждый раз при щелчке мышью пользователем.
  3. Мы будем передавать функции slideTo три параметра: позицию по оси x, позицию по оси y и еще одно значение, которое будет указывать скорость скольжения:
    _root.onMouseDown = function() {
      ball_mc.slideTo(this._xmouse, this._ymouse, 4);
    };

  4. Теперь нам нужно создать непосредственно функцию slideTo, которая должна будет выполнять два отдельных действия:
    • устанавливать в фильме значения targetX и targetY;
    • настраивать управляющий элемент enterFrame фильма для обеспечения его скольжения по направлению к конечной точке.

      Вместо того чтобы определять эту функцию для отдельного фильма, как мы делали в предыдущих функциях ball_mc.checkDistance, мы поместим ее в MovieClip.prototype. Все функции внутри MovieClip.prototype доступны в равной степени всем фильмам. Все встроенные методы фильмов, такие как goToAndPlay, также присутствуют в movieclip.prototype. При вызове функции она ведет себя так, как если бы она была внутри фильма.

       
      MovieClip.prototype.slideTo = function(x, y, speed) {
        // set up targets and speed variable
        this.targetX = x;
        this.targetY = y;
        this.speed = speed;

        // create onEnterFrame function
          this.onEnterFrame = function() {
          // take care of motion
          this._x += (this.targetX-this._x)/this.speed;
          this._y += (this.targetY-this._y)/this.speed;

          // check if near target
            if (Math.abs(this.targetX-this._x)<0.2
             && Math.abs(this.targetY-this._y)< 0.2) {
            this._x = this.targetX;
            this._y = this.targetY;
            delete this.onEnterFrame;
          }
        };
      };

      Первые три строки функции берут параметры, которые ей передаются, и сохраняют их в переменных внутри фильма. Затем присваивается функция onEnterFrame, передвигающая фильм, а также выполняется проверка достижения конечной точки.

       
    • Сохраните ваш файл под именем issueCommand1.fla и запустите его. При щелчке мышью фильм будет скользить к месту щелчка.
    • Мы также можем попытаться применить тот же самый подход в двух фильмах - создать копию исходного фильма ball_mc и дать новому инстансу имя ball_mc2 с помощью Property Inspector.
    • Перетащите инстанс ball_mc2 на рабочее место и затем откройте панель Actions для изменения кода onMouseDown, согласно тексту кода, приведенному ниже:
      _root.onMouseDown = function() {
        ball_mc.slideTo(this._xmouse, this._ymouse, 4);
        ball_mc2.slideTo(this._xmouse+19, this._ymouse, 1);
      };

    • Сохраните фильм в файле issueCommand1b.fla и запустите его. Вы заметите, что второй фильм перемещается значительно правее указателя мыши и со значительно меньшей скоростью.
     
 

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

 

Другая проблема состоит в том, что мы помещаем в фильм переменные, такие как targetX, targetY и speed, которые могут уже использоваться в фильме с другими целями. Они будут просто записываться поверх старых, что соответствующим образом повлияет на функциональность фильма. Несмотря на то, что мы обычно помним имена, присваиваемые объектам в нашем ActionScript, полезно использовать информативные и не лишенные смысла названия.

 

Использование пустых фильмов

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

 

Управляющий элемент mouseDown настраиваем так же, как и прежде:

 
_root.onMouseDown = function() {
  ball_mc.slideTo(this._xmouse, this._ymouse, 4);
};

Теперь наша функция slideTo будет выглядеть почти так же, как раньше, и основным отличием является то, что прежде фильм управлял сам собой, а теперь фильм выполняет внутри себя определенные действия. Это видно из замены 'this' на 'this._parent' при доступе или изменении параметров X и Y. Наш управляющий фильм осуществляет доступ и управление параметрами своего родительского фильма, т.е. того фильма, который необходимо перемещать.

 
MovieClip.prototype.slideTo = function(x, y, speed) {
  // create controller movieclip
  var control_mc = this.createEmptyMоvieClip ("slideControl",
        Кthis.depth++);
  control_mc.targetX = x;
  control_mc.targetY = y;
  control_mc.speed = speed;
  control_mc.onEnterFrame = function() {
    // this._parent is the movieclip we're moving
    this._parent._x += (this.targetX-this._parent._x) /this.speed;
    this._parent._y += (this.targetY-this._parent._y)/this.speed;
    if (Math.abs(this.targetX-this._parent._x)<0.2
      && Math.abs(this.targetY-
                Кthis._parent._y) <0.2) {
      this._parent._x = this.targetX;
      this._parent._y = this.targetY;
      this.removeMovieClip();
    }
  };
};

Как и в отношении функции duplicate, созданной нами ранее, мы использовали ссылку, возвращаемую функцией createEmptyMovieClip для обращения к вновь созданному movieClip. Одной из возможных "ловушек" при использовании этого метода с createEmptyMovieClip является то, что пользователь может записать фильм поверх уже имеющегося внутри. Проще говоря, это то, чего нужно остерегаться при управлении фильмом; необходимо иметь некий механизм определения того, на какой глубине находятся объекты и символы. Посредством ввода переменной глубины для каждой временной линии можно эффективно реализовать данную меру предосторожности, применяя этот способ каждый раз при создании фильма. С другой стороны, можно было бы объявить глобальную переменную глубины для всех временных линий, однако все же лучше иметь одну переменную для каждой временной линии, чтобы не терять контроль над значениями. Оставляем право выбора за вами.

 

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

 

Сохраните ваш фильм в файле issueCommand2.fla. Если вы запустите фильм на данном этапе, вы заметите, что движение будет прекращено при быстром последовательном щелчке мышью. Если выполнить команду Debug > List Variables, станет видно, что причиной этого является присутствие более чем одного инстанса slideControl в нашем фильме - все они работают с различными направлениями. Таким образом, нам нужно придумать что-то такое, с помощью чего можно будет убеждаться в присутствии в любой момент времени лишь одного инстанса этого управляющего клипа внутри нашего фильма.

 

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

 

Более разумным решением будет проверка того, имеется ли уже фильм slideControl. Если это не так, то вам нужно будет создавать его, а если он уже присутствует, то нужно будет перезаписывать переменные X и Y конечной точки и событие onEnterFrame.

 

Оба подхода приводят к одному и тому же результату.

 
MovieClip.prototype.slideTo = function(x, y, speed) {
  var control_mc
  if (this.slideControl) {
    //if slideControl already exists
    control_mc = this.slideControl;
  }
  else {
    //if slideControl doesn't exist then create it
    control_mc = this.createEmptyMovieClip
      ("slideControl", this.depth++);
  }
  control_mc.targetX = x;
  control_mc.targetY = y;
  control_mc.speed = speed;
  control_mc.onEnterFrame = function() {
    this._parent._x += (this.targetX-this._parent._x)/this.speed;
    this._parent._y += (this.targetY-this._parent._y)/this.speed;
    if (Math.abs(this.targetX-this.__parent._x)<0.2 &&
    КMath.abs(this.targetY-this._parent._y)<0.2) {
      this._parent._x = this.targetX;
      this._parent._y = this.targetY;
      this.removeMovieClip();
    }
  };
};

Сохраните файл под именем issueCommand3.fla и при запуске фильма обратите внимание на то, что теперь он ведет себя нужным образом.

 

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

 

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

 
function slideDone(mс) {
  trace("movieClip "+mc+" has finished moving");
}

Вообще говоря, когда движение фильма будет прекращаться, будет осуществляться вызов функции slideDone в _root. При вызове функции slideTo, нам нужно будет добавить два других параметра - callBackObj и callBackFunc. callBackObj является местоположением вызываемой функции (в данном случае, _root), а callBackFunc - именем вызываемой функции, т.е., в нашем случае, функции slideDone. Итак, сначала нужно добавить в нашу функцию два дополнительных параметра:

 
_root.onMouseDown = function() {
  ball_mc.slideTo(this._xmouse, this._ymouse, 4,  _root, "slideDone");
};

Затем нам потребуется настроить функцию slideTo для работы с этими двумя параметрами и для хранения их в фильме slideControl (посредством добавления кода):

 
MovieClip.prototype.slideTo =
 function(x, y, speed, callbackObj, callbackFunc) {
  var control_mc
  if (this.slideControl) {
    control_mc = this.slideControl;
  }
  else   {
    control_mc =
     this.createEmptyMovieClip("slideControl", this.depth++);
  }
  control_mc.targetX = x;
  control_mc.targetY = y;
  control_mc.speed = speed;
  control_mc.callBackObj = callBackObj;
  control_mc.callBackFunc = callBackFunc;
};

Наконец, нам нужно выяснить, как вызывать _root.slideDone с использованием двух переменных callBackObj и callBackFunc. Это на самом деле очень просто и делается практически таким же образом, как осуществляется, например, доступ к значению в массиве, или динамическое создание ссылки на фильм:

 
this.callBackObj [this.callBackFunk] (this._parent)

Часть кода перед квадратными скобками является местоположением функции (_root). Содержимое в квадратных скобках осуществляет поиск значения, отвечающего данной строке (в нашем случае, slideDone), и затем значение в скобках передается в виде параметра. Передаваемое здесь значение является обращением к фильму, который мы перемещали, т.е. this._parent, our ball_mc. Наша функция целиком выглядит примерно так:

 
MovieClip.prototype.slideTo =
 function (x, y, speed, callbackObj, callbackFunc) {
  var control_mc
  if (this.slideControl) {
    control_mc = this.slideControl;
  }
  else   {
    control_mc = this.createEmptyMovieClip
      ("slideControl", this.depth++);
  }
  control_mc.targetХ = x;
  control_mc.targetY = y;
  control_mc.speed = speed;
  control_mc.callBackObj = callBackObj;
  control_mc.callBackFunc = callBackFunc;

  control_mc.onEnterFrame = function() {
    this._parent._x += (this.targetX-this._parent._x) /this.speed;
    this._parent._y += (this.targetY-this._parent._y) /this.speed;

    if (Math.abs(this.targetX-this._parent._x)<0.2 &&
    КMath. abs(this.targetY-this._parent._y)<0.2) {
      this._parent._x = this.targetX;
      this._parent._y = this.targetY;
      this.callBackObj[this.callBackFunc](this._parent);
      this.removeMovieClip();
    }
  };
};

Сохраните ваш фильм в файле issueCommand004.fla и при запуске фильма вы увидите, что в окне Output отобразится сообщение "movieClip_level0.mc has finished moving", т.е. сообщение о завершении движения фильма. Это будет происходить каждый раз при остановке фильма.

 

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

 

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

 

Реализация подходов на практике

Сейчас настало время вновь обратиться к некоторым из уже рассмотренных подходов. То, о чем мы говорили ранее, может показаться однообразным, однако сейчас мы приведем несложный пример, использующий некоторые из изученных нами способов. В качестве примера создадим страницу Flash.

 

Обозреватель изображений

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

 
  1. Откройте новый фильм с разрешением (550x400 пикселей) и затем в Property Inspector установите частоту кадров на значение 31.
  2. Импортируйте фотографии, находящиеся в файлах на компакт-диске, прилагаемом к книге (001.jpg - 009.jpg), и преобразуйте каждый из них в фильм с левым верхним углом в качестве точки закрепления, назвав их соответственно по порядку именами 001-009.

     


     

     

     


     

     
  3. Теперь нужно дать имена всем фильмам с изображениями. С помощью Property Inspector присвойте им имена инстансов с c1 по c9.
  4. Расположите рисунки так, чтобы они прилегали друг к другу в порядке 3x3, и, выделив все рисунки, преобразуйте выделенную область в фильм с именем holder, указав точку закрепления в левом верхнем углу.

     


     

     

    Итак, теперь у нас на рабочем месте есть инстанс holder в корневой временной диаграмме. Мы добавим движение, переместив фильм holder под маску так, чтобы нужный рисунок оказался на нужной позиции.

     
  5. Выделив фильм holder, используйте Property Inspector, чтобы задать ему имя инстанса holder и указать его значения X и Y, установив их на 0,0. После этого точка закрепления будет размещена в левом верхнем углу рабочего места. Наконец, назовите текущий слой 'pictures'.
  6. Нам нужно будет создать маску, поэтому добавьте новый слой над слоем pictures и пометьте его как маску.
  7. Нарисуйте прямоугольник 200x240 пикселей любого цвета и с помощью Property Inspector задайте значения X и Y, равные 180,89.
  8. Преобразуйте выделенный прямоугольник в фильм с именем maskSquare, убедившись, что точка закрепления находится в левом верхнем углу. Наконец, с помощью Property Inspector дайте фильму maskSquare имя инстанса - maska.

     


     

     
  9. Теперь нужно добавить некоторый код, чтобы сделать прямоугольник маской. Создайте новый слой с именем scripts и в новом слое откройте панель Actions, чтобы добавить следующий код:
    holder.setMask (maska);

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

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

     


     

     
  11. Далее, на слое background1 нарисуйте светло-серый прямоугольник 202x202 пикселя и с помощью Property Inspector задайте его значения X и Y, равные 179,88. Теперь на слое background2 нарисуйте другой серый прямоугольник более темным цветом и размером 204x244, задав для него значения X и Y, равные 178,87. Это будет границей наших фильмов.

    Вы можете добавить любые другие нужные вам изображения на фоновые слои.

     
  12. Чтобы привести в движение фильм holder, мы будем использовать функцию slide, созданную ранее. Добавьте следующий код в слой scripts над только что вставленной вами строкой кода:
    speed = 4;
    MovieClip.prototype.slideTo =
     function(x, y, speed, callbackObj, callbackFunc) {
      Var mc_control
      if (this.slideControl) {
        mc_control = this.slideControl;
      }
      else {
        mc_control = this.createEmptyMovieClip
         ("slideControl" , this. depth++) ;
      }
      mc_control.targetX = x;
      mc_control.targetY = y;
      mc_control.speed = speed;
      mc_control.callBackObj = callBackObj;
      mc_control.callBackFunc = callBackFunc;

      mc_control. onEnterFrame = function() {
        this._parent._x += (this.targetX-this._parent._x) /this.speed;
        this._parent._y += (this.targetY-this._parent._y) /this.speed;
        if (Math.abs(this.targetX-this._parent._x)<0.2
          && Math.abs(this.targetY-
              Кthis._parent._y)<0.2) {
          this._parent._x = this.targetX;
          this._parent._y = this.targetY;
          this.callBackObj[this.callBackFunc](this._parent);

         
    this.removeMovieClip();
        }
      };
    };
    function slideDone(mc) {
      trace("movieClip "+mc+" has finished moving");
    }

    Для выполнения этого кода мы создадим несколько кнопок. Вместо того чтобы динамически создавать кнопки с использованием createEmptyMovieClip и createTextField (эти подходы мы рассмотрим позднее), мы создадим символ вручную и затем динамически применим его.

     
  13. Создайте новый фильм и назовите его butt. Выделите фильм в Library и щелкните на белом значке меню вверху панели заголовка Library. В меню выберите параметр Linkage:, чтобы открыть окно Linkage Properties.
  14. Отметьте поле Export for ActionScript, присвойте символу идентификатор butt и нажмите клавишу OK.

     


     

     
  15. Теперь вы будете находиться в корневом слое фильма butt. Разместите поле Dynamic Text внутри фильма и дайте ему имя инстанса tf с помощью Property Inspector. Размер текста нашего поля равен 9, шрифт - Arial, без встроенных шрифтов.
  16. Для автоматического добавления кнопок нам нужно добавить следующий код в слой scripts нашей корневой временной диаграммы (под уже имеющимся кодом).
    holder.setMask(maska);
    for (var i = 1; i<=9; i++) {
      var mc_control = _root.attachMovie("butt", "butt"+i, i);
      mc_control._x = 175+i*9;
      mc_control._y = 375;
      mc_control.mc = this.holder["c"+i] ;
      mc_control.tf.text = i;
    }

    Этот код циклически выполняется для каждого фильма с фотографией и добавляет кнопку. В нем используется итератор 'i' для установки текстового значения поля 'tf', поэтому в поле появятся числа от 1 до 9. В дополнение к этому, используется значение 'i' для установки конечного фильма для каждой кнопки (несмотря на то, что butt является фильмом, этот объект будет кнопкой, так как мы будем присваивать ему событие onPress). Число 9 в конце четвертой строки кода контролирует расстояние между всеми фильмами-кнопками.

     

    Перед присвоением события onPress нам нужно решить, какое именно действие будет выполняться при нажатии кнопки, так же как и место, в которое должен переместиться holder для корректного отображения каждой фотографии под маской.

     

    Все это можно сделать, рассмотрев конкретный случай. Например, если бы у нас был фильм, расположенный в точке 300,300 в фильме holder, где должен был бы быть расположен holder, чтобы правильно отображать фотографии под маской? Если бы мы расположили holder на том же месте рабочего стола, что и маску, то отображалось бы все, что было бы на позиции 0,0 в holder. Основываясь на этом, мы можем сделать вывод, что если бы нам нужно было отображать объект на позиции 300,300 в holder, мы могли бы переместить holder на 300 пикселей влево и на столько же вверх. В коде мы бы указали это следующим образом:

     
    (maska._x-300, maska._y-300);

    Теперь, если мы обратимся к координатам _x и _y любого из наших фильмов с изображениями, то получим координаты фильма внутри holder. Следовательно, можно сказать, что для того, чтобы каждый фильм был расположен строго под маской, нам необходимо перемещать holder на следующее место:

     
    (maska._x-mc._x, maska._y-mc._y);
  17. Итак, теперь мы можем построить функцию onPress для наших кнопок:
    for (var 1 = 1; i<=9; i++) {
      var mc_control = _root.attachMovie("butt" , "butt"+i, i);
      mc_control._x = 175+i*9;
      mc_control._y = 295;
      mc_control.mc = this.holder["c"+i] ;
      mc_control.tf.text = i;
      mc_control.onPress = function() {
        var x = this._parent.maska._x-this.mc._x;
        var у = this._parent.maska._y-this.mc._y;
        this._parent.holder.slideTo(x, y, this._parent.speed,
        Кthis._parent, "slideDone") ;
      };
    }

 

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

 
for (var i = 1; i<=9; i++) {
  var mc_control = _root.attachMovie("butt", "butt"+i, i);
  mc_control._x = 175+i*9;
  mc_control._y = 295;
  mc_control.mc = this.holder["c"+i] ;
  mc_control.tf .text = i;
  mc_control.onPress = function() {
    this._parent.holder.slideTo(this._parent.maska.
    К_x-this.mc._x, this._parent.maska._y-this.mc._y,
    Кthis._parent.speed, this._parent, "slideDone");
  };
}

Сохраните фильм в файле pictureMask.fla. При его запуске вы увидите, что при скольжении каждого рисунка на его позицию происходит регистрация происходящего в окне Output. Сейчас для нас это не имеет значения, однако позже мы разберемся, как использовать эту возможность для вызова какого-либо события, например, текстового эффекта. Это лишь однa из возможных применений этого окна. Однако этот вид управления также может быть использован для вывода некоторого пояснительного текста, так, чтобы рисунки являлись фоном интерфейса, или для запуска анимации. Необходимо заметить, что мы управляем движением, которое сами же и инициировали. Мы знаем, когда оно начинается, и можем быть оповещены о его завершении, а это означает, что оно может стать частью цепи событий.

 

источник: http://www.INTUIT.ru

 

 

13 центов(0,13$) за клик, выплаты через WebMoney каждый вторник +10% с рефералов

Мы выкупаем 100% трафа! $12 за 1000 хостов (РФ), и до $4 за 1000 хостов (зарубежный траф) + 10% с дохода Ваших рефералов!
 Выплаты через
WebMoney

~80-100$ за1000 хостов 2.5$ за 1 смс.
реф. процент - 10 %Выплаты происходят раз в неделю, в четверг на
WebMoney
 
 

 

____________________________

Посмотреть порно видео в онлайне »

_______________________________

 

   
   
Сайт управляется системой uCoz