Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование игр на Flash/Flex


Добрый день, уважаемые читатели!

В этом выпуске (статье) мы рассмотрим способ задания направления объекта с помощью тригонометрических функций. В отличие от Джоба Макара, я полагаю, что основные сведения из тригонометрии в Ваших головах сохранились, поэтому сразу рассмотрим результат. Ниже следует код основного модуля, разработанного в замечательной программе 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


В избранное