Опубликован: 07.11.2006 | Уровень: специалист | Доступ: платный
Лекция 9:

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

Пружинящие объекты

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

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

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

  • Пружина, как правило, ускоряется по направлению к определенной точке. Если она пройдет эту точку, ее движение замедлится, направление движения поменяется, и начнется ускорение в обратную сторону по направлению к той же точке.
  • Ускорение пропорционально расстоянию между объектом и конечной точкой.

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

Теперь рассмотрим некоторые иллюстрации. На первом рисунке показана воображаемая пружина, полностью оттянутая назад. Ускорение максимально и равно, скажем, +30.


Представьте себе эту ситуацию во Flash: объект начинает двигаться со скоростью 30 пикселей в кадр. В следующем кадре объект становится несколько ближе к цели и пружина уже натянута чуть слабее. Она добавляет ускорение, скажем, равное 20. Итак, теперь объект двигается со скоростью 50 пикселей в кадр. Этот принцип очень важно понимать. Объект не замедляется, а все еще ускоряется - т.е. продолжает увеличивать скорость - но увеличение его скорости не постоянно во времени.


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


Перейдем к следующему кадру. Объект движется так быстро, что "вылетает" за пределы конечной точки, наподобие собаки, гоняющейся за мячиком по льду. Теперь цель находится "за" объектом. Сейчас пружина будет действовать на объект с силой, обеспечивающей обратное ускорение объекта. Когда объект будет находиться достаточно далеко по другую сторону от конечной точки, ускорение, очевидно, будет довольно сильным, достаточным для остановки объекта. Предположим, на объект действует ускорение величиной -15. Наш объект все еще движется, однако его скорость уменьшается до значения 38.


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


Итак, нужно перевести эту теорию на язык ActionScript. Давайте воссоздадим это пружинящее движение во Flash.

Пружина
  1. Откройте новый основной фильм и создайте в нем новый клип. Как обычно, я создал шарик с именем инстанса ball_mc. В середине экрана (275, y) нарисуйте простую линию. Она будет играть роль графического представления конечной точки, на которой будет базироваться наше пружинящее движение.

  2. Добавьте новый слой с именем actions и в кадре 1 объявите переменную для представления нашей конечной точки (в этом упражнении мы используем разрешение по осям).
    var centerX = 275;
  3. Теперь нам нужно определить "пружинящий" множитель или, говоря более определенно, насколько сильное ускорение будет действовать на объект на каждом расстоянии. Он будет выражен в виде дроби. По существу, мы будем брать отношение расстояния между объектом и точкой закрепления пружины и использовать его в качестве значения ускорения. Нам подойдут значения около 0,2. Oднако вы можете поэкспериментировать с различными величинами, чтобы достичь желаемого результата. Этот множитель обычно обозначается k. Это не очень информативно, однако, если использовать его всегда, вы будете понимать, что означает k. Итак, вот наш файл.
    var centerX = 275;
      var k = .2;
  4. Мы настроили рабочее место, и можно приступать к реализации действия. Сначала необходимо определить расстояние по одному измерению - вычесть ball_mc._x из centerX. После этого умножаем расстояние на k, чтобы получить значение ускорения, которое будет записано в переменную accX. Затем прибавляем accX к нашей скорости velX и, наконец, прибавляем скорость к ball_mc._x. Мы реализуем эти сложения под двумя имеющимися строками в функции onEnterFrame.
    onEnterFrame = function () {
        dx = centerX-ball_mc._x;
        accX = dx*k;
        velX += accX;
        ball_mc._x += velX;
      };

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

    ball_mc._x += velX += (centerX-ball_mc._x)*k;

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

  5. Если сейчас запустить фильм, на экране появится "красиво" пружинящий около точки закрепления объект. Но есть одна проблема: мы реализовали идеальный случай, в котором отсутствуют силы трения и всякая потеря энергии, поэтому наш объект будет совершать пружинящие колебания вечно. Давайте добавим некоторое трение, аналогично тому, как мы это сделали в примере с "бросанием" объекта в "Интерфейсы AсtionScript" . Мы будем просто умножать скорость на дробь вроде 0,9 в каждом кадре. Благодаря этому колебание объекта будет замедляться, что сделает данный пример более реалистичным. Просто добавьте следующую строку.
    var centerX = 275;
      var k = .2;
      onEnterFrame - function () {
        dx = centerX-ball_mc._x;
        accX = dx*k;
        velX += accX;
        velX *= .9;
        ball_mc._x += velX;
      };
  6. Запустите фильм и вы получите довольно реалистичное пружинящее движение.

    Можно легко продолжить работу и изменить этот файл так, что пружинящее движение будет осуществляться по осям x и y. Я реализовал это и сделал ball_mc перетаскиваемым в исходном файле Spring_2_dimensions.fla, на случай, если вы решите заняться дальнейшим экспериментированием. Весь код обсуждался ранее, поэтому я не буду останавливаться на этом файле. Если вы запустите его, вы сможете "зацеплять" и "бросать" мячик, и он всегда, в конечном счете, будет возвращаться в центр экрана.


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

  • Вместо фиксированной конечной точки ( centerX, centerY ), сделайте конечную точку перемещаемой. Попробуйте использовать ( this._xmouse, this._ymouse ) для определения положения точки.
  • Вы можете создать другой перетаскиваемый фильм с именем anchor_mc. Заставьте шарик пружинить по направлению к точке ( anchor_mc._x, anchor_mc._y ).
  • Чтобы отобразить графически само колебание, добавьте следующий код в конец функции spring, после перемещения ball на новую позицию.
    clear();
      lineStyle(1, 0, 100);
      moveTo(centerX, centerY);
      lineTo(ball_mc._x, ball_mc._y);
  • Наконец, добавьте гравитацию! Не существует причин, по которым на ваш объект не может действовать несколько сил ускорения. Просто добавьте в файл строку velY += grav ; а перед этим укажите значение для grav. Вы увидите, что вам потребуется указать гораздо большее значение гравитации, нежели в предыдущих примерах. С другой стороны, можно немного уменьшить коэффициент k.

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

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

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

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

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

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

Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989