Толик Панков
hex_laden
............ .................. ................
Толик Панков [userpic]
Вращение объекта 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

Comments
(Anonymous)

>2012
>flash

и?
студенты изучают, вопросы задают.
Наше дело написать мануал

Соглашусь.
Особенно средства поддержки кода там зло.
Хорошие средства разработки умеют делать только ребята из Редмонта.