Опубликован: 07.11.2006 | Доступ: свободный | Студентов: 3400 / 338 | Оценка: 3.94 / 3.71 | Длительность: 37:11:00
Лекция 2:

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

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

Чтобы не забивать фильм слишком большим количеством дубликатов одного и того же объекта, мы можем присвоить каждому дубликату свою собственную функцию 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. По большому счету, в нашем фильме ничего не происходит - он просто находится в ожидании щелчка мыши, чтобы запуститься вновь.

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

Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

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