Движение: замедление и отскакивание
Это руководство охватывает тему «замедление движения». Часто задают вопрос: «Как сделать так, чтобы объект, движущийся к определенной точке, плавно замедлял свое движение по мере приближения к цели, аккуратно вставая на место?» Это я и называю «замедлением», и это довольно просто, если вы только поймете, с какой стороны за это взяться. Благодаря «замедлению» можно создавать реалистичные эффекты движения.
Представьте, что вы ведете машину по шоссе со скоростью 60 км/ч, направляясь домой. Вы же не станете ехать со скоростью 60 км/ч вплоть до подъезда вашего дома чтобы мгновенно остановиться как только прибудете на место. Вы замедлите скорость до 40, затем до 25, 15, 10, 6, 4, 2, 1 и остановитесь. И начинаете движение вы похожим образом, постепенно набирая скорость. Это будет «разгон». Я собираюсь в этом руководстве поговорить о «замедлении» и постараюсь сделать это поподробней.
Замедление реализуется посредством одной простой формулы, которую можно подогнать или модифицировать так, чтобы создать именно тот эффект, который вы хотите. Однажды разобравшись, вы можете использовать ее не только для движения, но и для создания эффектов при вращении объектов, при масштабировании, прозрачности и даже изменении цвета. В любой ситуации, когда вы хотели бы плавно изменить какое-либо состояние.
Ну ладно, давайте разбираться с физикой.
Вы находитесь в каком-то одном месте и хотите попасть в другое.
Сначала давайте сделаем это в виде прыжка. Мы создадим объект и ситуацию, к которыми будем работать на протяжении всего этого руководства. Создайте что-нибудь любой формы по вашему выбору, сконвертируйте это в мувиклип и вставьте следующий код:
onClipEvent(load){
_x=0;
_y=0;
}
onClipEvent(mouseDown){
targetx=_root._xmouse;
targety=_root._ymouse;
}
onClipEvent(enterFrame){
_x=targetx;
_y=targety;
}
Что он делает:
1. Сначала помещает объект в 0,0
2. Когда нажимается кнопка мыши, то координаты мыши помещаются в targetx и targety
3. Перемещает координаты мувиклипа в targetx и targety
Проверьте. Где бы ни был объект, когда вы кликаете мышкой, объект перемещается под мышиный курсор. Он делает это мгновенно, в одном фрейме.
Отлично, теперь давайте сделаем первое замедление. Теория следующая:
1. Мы знаем, где мы находимся.
2. Мы знаем, куда мы хотим перейти.
3. Мы можем оценить расстояние отсюда до сюда.
4. Мы перемещаемся ровно на половину расстояния.
5. С нашей новой позиции...
1. Мы опять знаем, где находимся.
2. Куда мы идем, мы тоже знаем - оно не менялось.
3. Вычисляем новое расстояние.
4. Перемещаемся ровно на половину расстояния.
5. Опять начинаем с п. 1.
С каждым витком цикла мы движемся все меньше и меньше. Так мы начинаем движение довольно быстро и движемся все медленнее и медленнее по мере приближения к цели. Теоретически, мы никогда по-настоящему не достигнем цели, ведь не важно насколько мы близки к ней, мы всегда делаем половину шага. Но когда вы на расстоянии 1/100-й пикселя от цели, вы можете спокойно считать, что достигли ее!
Итак, переводя все это на ActionScript, я сначала, для ясности, проведу каждое вычисление в отдельной строке кода. Позже я покажу вам укороченную формулу, которая должна намертво запечатлеться в вашем мозгу. Также, для простоты, мы начнем с движения только по _x. Затем мы просто добавим такие же строки для _y.
Вот оно:
onClipEvent(load){
_x
_x=0;
distx
_y=200;
}
onClipEvent(mouseDown){
targetx=_root._xmouse;
movex
}
new _x
onClipEvent(enterFrame){
distx=targetx-_x;
movex=distx/2;
_x+=movex;
}
(примечание: Некоторые люди спрашивали, что такое «+=». Это оператор инкрементирующего присваивания. Он берет переменную, прибавляет к ней значение и присваивает результат обратно той же переменной. Т.е. _x+=movex означает то же самое, что самое, что и _x=_x+movex )
Говоря языком шагов, описанных нами ранее:
1. Мы находимся в _x.
2. Мы хотим попасть в targetx.
3. Дистанция равна targetx-x или distx
4. Половина distx равна distx/2, которую мы присваиваем movex и затем прибавляем к _x: _x+=movex.
5. Следующий фрейм начинается с п.1.
Проверьте это. Теперь, когда мы кликаем мышкой, объект не просто сразу прыгает в эту точку, но плавно скользит туда. Да, конечно на этой стадии мы движемся лишь в горизонтальной плоскости, т.к. мы еще ничего не делали с _y. До того, как мы займемся ей, давайте сделаем наш код более компактным и избавимся от нескольких лишних переменных. Надеюсь, вы сможете разобраться в этих изменениях:
onClipEvent(load){
_x=0;
_y=200;
}
onClipEvent(mouseDown){
targetx=_root._xmouse;
}
onClipEvent(enterFrame){
_x+=(targetx-_x)/2;
}
Теперь в одной строке: _x+=(targetx-_x)/2 мы определяем расстояние, делим его на 2 и прибавляем к _x.
Если вы следили за мыслью до этого места, то можете спокойно сами добавить свой код для _y. Не забудьте targety в первом блоке кода:
onClipEvent(load){
_x=0;
_y=0;
}
onClipEvent(mouseDown){
targetx=_root._xmouse;
targety=_root._ymouse;
}
onClipEvent(enterFrame){
_x+=(targetx-_x)/2;
_y+=(targety-_y)/2;
}
Проверьте это, объект должен плавно переместиться прямо в точку, которую вы кликнете. Довольно круто до сих пор, но мы еще не закончили.
Если я вижу цифру в коде, типа «2» в нашем, это меня раздражает. Я почти всегда стремлюсь заменить их переменными, особенно, если я могу захотеть поменять их в определенный момент (это то, что мы собираемся сделать). Вот окончательный код, который мы будем использовать:
onClipEvent(load){
_x=0;
_y=0;
speed=2;
}
onClipEvent(mouseDown){
targetx=_root._xmouse;
targety=_root._ymouse;
}
onClipEvent(enterFrame){
_x+=(targetx-_x)/speed;
_y+=(targety-_y)/speed;
}
Теперь довольно очевидно и естественно поиграть с переменной speed. Если вы установите ее в 1, то увидите, что клип ведет себя точно так же, как самый первый, который мы сделали. Объект просто прыгнет в цель за один шаг. Чем выше значение переменной speed, тем медленнее будет движение.
Предположим, мы установили ее в 10. Программа посчитает расстояние перемещения и будет двигаться лишь на 1/10 этого расстояния. Затем на 1/10 оставшегося расстояния. Все перемещение займет долгое время. Вы можете подогнать эту переменную, чтобы создать именно тот эффект, который вы хотите.
И еще один бонус. Попробуйте установить переменную speed где-то между 0.5 и 1.0. Я обнаружил, что 0.6 приводит к приятному эффекту. Создается эффект «отскакивания» или «резинки». Вы теперь делите расстояние на дробное число. Это заставляет объект двигаться дальше, чем дистанция до цели. Он перелетает цель и улетает дальше. Затем он летит обратно, снова перелетает, но уже не настолько далеко, как в первый раз. И так далее, пока не остановится.
Вот и все, что я хотел сказать про замедление. На самом деле, существуют более сложные формулы, которые используют различные математические функции, но я думаю, что вы обнаружите, что приведенная формула довольно быстрый и простой путь достижения нужного результата в 99% случаев. Привыкнув к ней, вы можете экспериментировать с другими свойствами мувиклипов: _rotation, _alpha, scale и так далее. В заключение, я хочу привести общую формулу, которую вы должны запомнить:
СледующийШаг = (КудаМыХотимПойти - ГдеМыСейчасНаходимся)/Скорость;
Все обычно заканчивается на формуле:
Свойство = (Цель - Свойство) / Скорость;
|