Вращение объекта Movie Clip вокруг своего центра в Adobe Flash с использованием Actionsript 2.0

Данный способ подходит не только для вращения объекта вокруг центра, но также и для вращения объекта вокруг любой точки, находящейся внутри него.
За поворот MovieClip’а отвечает свойство _rotation, которому необходимо передать угол поворота объекта в градусах. Все бы ничего, но поворачивается объект вокруг собственной точки регистрации:


[Youtube] [Скачать SWF] [Смотреть SWF]

Код первого кадра:

onEnterFrame=function()
{
imvVert._rotation++;
}



Точка регистрации на сцене и в библиотеке (выделена красной рамкой)

И если для созданных в редакторе MovieClip’ов не это составляет особых проблем, т.к. изображение внутри клипа можно передвинуть вручную, относительно точки регистрации или задать точку регистрации при создании клипа:

[Youtube] [Скачать SWF] [Смотреть SWF]

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


Точка регистрации и центр

А вращать объект, например, надо вокруг его центра.
Подготовительный этап

1. В данном примере будет использоваться изображение, загруженное в заранее созданный пустой MovieСlip из внешнего источника. Поэтому, вначале создается собственно сам пустой MovieClip в библиотеке, (названный в примере mvVictim), он помещается на сцену и его экземпляру (Instance) присваивается имя. В данном примере – imvVictim

Далее, в первый кадр добавляется следующий код:

stop(); //останавливаем воспроизведение
var MovieName="123.png"; //имя загружаемой картинки (должна лежать в том же каталоге, что и flash ролик)
var LoadComplete=false; //флаг-индикатор, показывает загрузилось изображение или нет
var lisVictim:Object = new Object();//создали слушатель для клипа
//обработчик слушателя*****************************
lisVictim.onLoadInit = function(mc:MovieClip)
{
//устанавливаем начальное состояние клипа, ставим его по центру:
imvVictim._x=(Stage.width-imvVictim._width)/2;
imvVictim._y=(Stage.height-imvVictim._height)/2;
LoadComplete=true;
}
//конец обработчика*********************************
//создаем объект-загрузчик
var imageLoader:MovieClipLoader = new MovieClipLoader();
imageLoader.addListener(lisVictim); //подключаем слушатель
imageLoader.loadClip(MovieName, imvVictim);  //загружаем клип
//*************************************************************

Если запустить ролик на выполнение сейчас, то будет отображено статичное изображение из файла 123.png, находящееся в центре сцены
2. Для работы с углами во время расчетов и отрисовки вращения будет необходимо преобразовывать градусы в радианы, т.к. математические функции такие как Math.sin, Math.cos требуют величин в радианах, а свойству _rotation, объекта MovieClip необходимо присваивать значение угла в градусах.
Преобразование градусов в радианы производится по следующим формулам:


Где Ag – значение угла в градусах, Aк – в радианах
В виде программного кода функции преобразования выглядят так:

//преобразования градусов в радианы и обратно
function gradToRad(grad:Number):Number
{
rad=grad*Math.PI/180;
return rad;
}
function radToGrad(rad:Number):Number
{
grad=rad*180/Math.PI;
return grad;
}


Расчеты

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

Нам известны координаты объекта Xо и Yо, они же координаты точки регистрации, а также координаты точки, вокруг которой объект должен вращаться Хт;Yт, а также угол Aо на который необходимо повернуть объект относительно точки, вокруг которой он будет вращаться
Сначала найдем отрезок a:

Далее найдем угол

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

И новые координаты объекта с учетом этого угла:

Реализация

Под координатами имеются ввиду координаты относительно ролика, а не внутренней системы координат MovieClip'а

1. Определим необходимые переменные и инициализируем их нулевыми значениями до произведения всех действий. Сразу скажу, их может быть и нужно меньше, чем в примере, но так код более читабелен и понятен.
Необходимо добавить этот код перед onLoadInit

var x_obj=0; //Координаты объекта
var y_obj=0;
var x_t=0; //Координаты точки, вокруг которой будем вращать
var y_t=0;
var alph=0; //угол Alpha - см картинку
var a_vect=0; //отрезок a - см картинку
var ugol=0; //угол на который надо поворачивать фигуру
var ugol_tp=0; //Угол используемый для вычисления поправки координат (A')


2. В обработчик onLoadInit перед установкой флага завершения загрузки добавляется следующий код:

x_obj=imvVictim._x; //запоминаем координаты объекта
y_obj=imvVictim._y;
x_t=x_obj+imvVictim._width/2; //... и координаты точки, вокруг которой будем вращать,
y_t=y_obj+imvVictim._height/2; // в данном случае - центра объекта
a_vect=Math.sqrt(Math.pow(x_t-x_obj,2)+Math.pow((y_t-y_obj),2)); //вычисляем длину отрезка a
alph=Math.asin((y_t-y_obj)/a_vect) //угол alpha в радианах


Функция Math.sqrt (n) возвращает значение квадратного корня числа n, а функция pow (n,m) – значение числа n в степени m.
3. Создаем функцию vrach () которая будет выполнять действия по непосредственному повороту объекта

function vrash()
{
ugol+=1; //значение угла будет увеличиваться при каждом вызове функции vrash()
ugol_tp=180+radToGrad(alph)+ugol; //вычисляем угол поправки A'
x_obj=a_vect*Math.cos(gradToRad(ugol_tp))+x_t; //... новые координаты объекта
y_obj=a_vect*Math.sin(gradToRad(ugol_tp))+y_t;
//передаем объекту новые параметры
imvVictim._x=x_obj;
imvVictim._y=y_obj;
imvVictim._rotation=ugol;
}


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

onEnterFrame=function()
{
if (LoadComplete) //проверка, произведена ли загрузка изображения и установка начальных параметров
{
vrash();
}
}


Модификация кода

1. Изменение направления вращения (по/против часовой стрелки)
Для изменения направления вращения достаточно изменить знак у числа, прибавляемого к переменной ugol в функции vrash()
Для того, чтобы вращающийся объект двигался, например, по оси X, достаточно ввести одну переменную там же где и предыдущие
var mtn=0;
и немного модифицировать код функции vrach()

...
mtn++;
imvVictim._x=x_fig+mtn;
...


Исходник:

stop(); //останавливаем воспроизведение
var MovieName="123.png"; //имя загружаемой картинки (должна лежать в том же каталоге, что и flash ролик)
var LoadComplete=false; //флаг-индикатор показывает загрузилось или нет
var lisVictim:Object = new Object();//создали слушатель для клипа
var x_obj=0; //Координаты объекта
var y_obj=0;
var x_t=0; //Координаты точки, вокруг которой будем вращать
var y_t=0;
var alph=0; //угол Alpha - см картинку
var a_vect=0; //отрезок a - см картинку
var ugol=0; //угол на который надо поворачивать фигуру
var ugol_tp=0; //Угол используемый для вычисления поправки координат (A')
//преобразования градусов в радианы и обратно
function gradToRad(grad:Number):Number
{
rad=grad*Math.PI/180;
return rad;
}
function radToGrad(rad:Number):Number
{
grad=rad*180/Math.PI;
return grad;
}
//обработчик слушателя*****************************
lisVictim.onLoadInit = function(mc:MovieClip)
{
//устанавливаем начальное состояние клипа:
imvVictim._x=(Stage.width-imvVictim._width)/2; //по центру
imvVictim._y=(Stage.height-imvVictim._height)/2;
//устанавливаем начальные значения переменных, используемых для вращения
x_obj=imvVictim._x; //запоминаем координаты объекта
y_obj=imvVictim._y;
x_t=x_obj+imvVictim._width/2; //... и координаты точки, вокруг которой будем вращать,
y_t=y_obj+imvVictim._height/2; // в данном случае - центра объекта
a_vect=Math.sqrt(Math.pow(x_t-x_obj,2)+Math.pow((y_t-y_obj),2)); //вычисляем длину отрезка a
alph=Math.asin((y_t-y_obj)/a_vect) //угол alpha в радианах
LoadComplete=true; //устанавливаем флаг завершения загрузки изображения
}
//конец обработчика*********************************
//создаем объект-загрузчик
var imageLoader:MovieClipLoader = new MovieClipLoader();
imageLoader.addListener(lisVictim); //подключаем слушатель
imageLoader.loadClip(MovieName, imvVictim);  //загружаем клип
//*************************************************************
//*************************************************************trace
function vrash()
{
ugol+=1; //значение угла будет увеличиваться при каждом вызове функции vrash()
ugol_tp=180+radToGrad(alph)+ugol; //вычисляем угол поправки A'
x_obj=a_vect*Math.cos(gradToRad(ugol_tp))+x_t; //... новые координаты объекта
y_obj=a_vect*Math.sin(gradToRad(ugol_tp))+y_t;
//передаем объекту новые параметры
imvVictim._x=x_obj;
imvVictim._y=y_obj;
imvVictim._rotation=ugol;
}
onEnterFrame=function()
{
if (LoadComplete) //проверка, произведена ли загрузка изображения и установка начальных параметров
{
vrash();
}
}

Ролик 1

[Youtube] [Скачать SWF] [Смотреть SWF]
Ролик 2

[Youtube] [Скачать SWF] [Смотреть SWF]

Скачать исходники (Adobe Flash CS 6) [Yandex.Disk]
Скачать исходники (Adobe Flash CS 6) [Mega.nz]
Исходник 1 ролика на PasteBin Исходник 2 ролика на PasteBin
(L) Kevin Kurt, Hex_Laden

Это перепост заметки из моего блога на LJ.ROSSIA.ORG
Оригинал находится здесь: http://lj.rossia.org/users/hex_laden/103589.html
Прокомментировать заметку можно по ссылке выше.