В этом выпуске (статье) мы рассмотрим способ задания направления объекта с помощью тригонометрических функций. В отличие от Джоба Макара, я полагаю, что основные сведения из тригонометрии в Ваших головах сохранились, поэтому сразу рассмотрим результат. Ниже следует код основного модуля, разработанного в замечательной программе Adobe
Flex. Я уже рассказывал, как можно получить ее бесплатно на сайте разработчика. Правда, для этого нужно быть студентом, или преподавателем.
Код основного модуля с комментариями
// Демонстрация поворота. Тригонометрия. События мыши. package { import flash.display.Bitmap; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.text.TextField; import flash.utils.Timer; public class MouseMove extends Sprite { private var _rocket:Sprite = new Sprite(); private var _field:Sprite = new Sprite; private var _txt:TextField = new TextField(); private var _bitmap:Bitmap// = new Bitmap(); private var _pictLoader:PictLoader = new PictLoader(this); private var _timer:Timer = new Timer(100); public const WIDTH:uint = 450 public const HEIGHT:uint = 350; public const BORDER:uint = 10; public const WIDTH1:uint = WIDTH -
BORDER*2 public const HEIGHT1:uint = HEIGHT - BORDER*2; public const ROCKETWIDTH:uint = 12; public const ROCKETHEIGHT:uint = HEIGHT / 4; public function MouseMove() { _pictLoader = new PictLoader(this); _pictLoader.bitmapLoad("images/forGames/rocket1.gif");
_timer.addEventListener(TimerEvent.TIMER,tick); _txt.x = BORDER + BORDER; _txt.y = BORDER; _txt.height = 80; _txt.width = WIDTH - 4*BORDER; _txt.wordWrap = true; _txt.htmlText = "<b>Демонстрация поворота. Тригонометрия. События мыши. Таймер.</b>\n Ракета вращается вслед за указателем мыши. Нажмите и удерживайте кнопку мыши. Ракета двигается" + " к ее указателю (запуск таймера). При отпускании кнопки ракета останавливается (остановка таймера)"; with(_field){
graphics.lineStyle(2,0); //Рисуем двойной барьер на рабочем поле. graphics.beginFill(0xFFFFFF); graphics.drawRoundRect(0,0,WIDTH,HEIGHT,WIDTH
/ 10,HEIGHT / 10); graphics.endFill(); graphics.drawRoundRect(BORDER,BORDER,WIDTH1,HEIGHT1,WIDTH1 / 10,HEIGHT1 / 10); addChild(_txt); addEventListener(MouseEvent.MOUSE_MOVE,rocketMove); addEventListener(MouseEvent.MOUSE_DOWN,mDown); //addEventListener(MouseEvent.CLICK,mDown); //Если убрать комментарий, один и тот же слушатель будет у двух событий мыши addEventListener(MouseEvent.MOUSE_UP,mUp);
}
addChild(_field); _field.addChild(_rocket); } public function answer(bitmap:Bitmap):void{ // Метод вызывается загрузчиком файла изображения with (bitmap){ width = ROCKETWIDTH; height = ROCKETHEIGHT; rotation = 180; x = ROCKETWIDTH / 2; y = height; } with (_rocket){ x = WIDTH / 2; y = HEIGHT * 0.8; rotation = 180; addChild(bitmap); }
} private function rocketMove(e:MouseEvent):void{ var distX:Number = mouseX - _rocket.x; if (_rocket.y >
mouseY)var distY:Number = _rocket.y - mouseY; // Используем библиотеку Math, в которой содержатся математические функции. else distY = mouseY - _rocket.y;
var beta:Number = Math.atan(distX/distY); var betaGr:Number = beta*180/Math.PI+180; if (mouseY > _rocket.y) betaGr = 180 - betaGr; _rocket.rotation = betaGr; /*with(_field){ // Если убрать знаки комментария, то будут вычерчиваться треугольники graphics.moveTo(_rocket.x,_rocket.y); // при этом данный обработчик следует назначить событию Click graphics.lineTo(mouseX,mouseY); // иначе все покроется треугольниками graphics.lineTo(_rocket.x,mouseY); graphics.lineTo(_rocket.x,_rocket.y); }*/ } private function mDown(e:MouseEvent):void{ // При нажатии на кнопку мыши таймер начинает работать _timer.start(); } private function mUp(e:MouseEvent):void{ // При отпускании кнопки мыши таймер перестает работать _timer.stop(); } private function tick(e:TimerEvent):void{ // Перемещаем изображение ракеты (контейнер) в точку расположения указателя мыши var dx:int = mouseX -_rocket.x; var dy:int = mouseY - _rocket.y; _rocket.x += dx / 4; _rocket.y += dy / 4;
}
} }
На рисунке я попытался пояснить, откуда берутся формулы для подсчета угла направления ракеты.
Модуль загрузки
В одном из предыдущих выпусков я продемонстрировал
загрузку файлов изображения. Здесь для полноты картины приведен соответствующий текст:
// Загрузчик изображений package { import flash.display.Bitmap; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; public class PictLoader extends Sprite{ private var _loader:Loader = new Loader(); private var __parent:Object; public function PictLoader(pa:Object){ // Ссылка на объект - родитель,
которому требуется картинка __parent = pa; } public function bitmapLoad(imgName:String):void{ _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete); //Связь со слушателем события "Завершение загрузки" _loader.load(new URLRequest(imgName)); }
private function onComplete(e:Event):void{//Вызывается при завершении загрузки var image:Bitmap = new Bitmap; image = Bitmap(_loader.content); // Запишем результат загрузки в объект Bitmap __parent.answer(image); // и вызовем метод answer у родителя. } } }
Обсуждение
Основная проблема, которую нужно решить при управлении объектами, содержащими растровые изображения - это расположение точки привязки. Напомню, что точка привязки определяет текущее положение объекта, то есть, когда мы пишем, например:
_rocket.x = WIDTH / 2;
то объект устанавливается по оси ОХ таким образом, что точка его привязки будет иметь указанное
значение. Важно также, что вращение объекта, происходящее при изменении свойства rotation, выполняется вокруг этой же точки. В нашем примере нужно, чтобы изображение ракеты поворачивалось вокруг центра нижней линии, а по умолчанию точка привязки - это верхний левый угол картинки. Поместив изображение в контейнер, удалось решить эту проблему.
Все остальное, полагаю, несложно будет разобрать на основе приводимого текста. Буду рад ответить на возникающие вопросы. Мой адрес доступен для читателей рассылки
и для зарегистрированных пользователей сайта http://master-teacher.ru