Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 25.02.2013, 20:34
Toothbrusher вне форума Посмотреть профиль Отправить личное сообщение для Toothbrusher Найти все сообщения от Toothbrusher
  № 1  
Ответить с цитированием
Toothbrusher

Регистрация: Feb 2013
Сообщений: 11
По умолчанию Sprite не желает становится растровым

Добрый вечер знатокам, помогите решить задачу!

У меня рисуется экземпляр Спрайта (а точнее, класса Litera) пользователем (с помощью "мела"-мыши - класс Chalk) на доске (класс Desk).
Затем я хочу перевести его в растр (по правому клику мышки на нем). Но возникает какая-то лажа с координатами, хотя все мои объекты непосредственные детишки stage, и между ними нет иерархий.
Я добавляю curr:БитмапДата на сцену, чтобы посмотреть, что же он в себя поместил методом draw(). В лучшем случае в нем имеется кусочек моего спрайта (если он нарисован ближе к правому краю окна). Но ведь спрайт должен рисоваться в позиции (0,0) объекта curr?!
И после всего этого безобразия мышь-мел тоже сбивается с истиного пути и теряет правильные координаты. В чем ошибка, не могу понять.


Код AS3:
package  {
	public class Main extends MovieClip{
		public var desk:Desk=new Desk();
		var chalk:Chalk=new Chalk();
		var letter:Litera;
 
		public function Main() {
 
			// constructor code
			desk.x=50;
			desk.y=50;
			stage.addChild(desk).name="desk";
 
			chalk.x=desk.width+desk.x+10;
			chalk.y=desk.height+desk.y - chalk.height;
			stage.addChild(chalk).name="chalk";
 
 
			desk.addEventListener(Chalk.CATCH, desk.drawStart);
			desk.addEventListener(Chalk.UNCATCH, desk.drawStop);
 
 
			letter=(Litera) (desk.letter);
			stage.addChild(letter).name="letter";
			stage.swapChildren(letter, chalk);
 
			var delButton:DelButt=new DelButt();
			delButton.x=desk.width+desk.x+10+delButton.width/2;
			delButton.y=desk.height+desk.y - chalk.height - 30;
			stage.addChild(delButton);	
		}	
	}
}
Код AS3:
package  {
	public class Litera extends Sprite{
 
		public function Litera() {
			// constructor code
			addEventListener(MouseEvent.MOUSE_DOWN, startDragM);
			addEventListener(MouseEvent.MOUSE_UP, stopDragM);
			addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, compare);
		}
 
 
		function startDragM(e:MouseEvent):void{
			this.startDrag();
		}
		function stopDragM(e:MouseEvent):void{
			this.stopDrag();
		}
		function clean():void{
			this.graphics.clear();
 
		}
 
		function lockListen():void{
			removeEventListener(MouseEvent.MOUSE_DOWN, startDragM);
			removeEventListener(MouseEvent.MOUSE_UP, stopDragM);
			removeEventListener(MouseEvent.RIGHT_MOUSE_DOWN, compare);
		}
 
		function compare(e:MouseEvent):void{
			var avec:expA=new expA();  //растр,  с кот. потом будет сравниваться Litera
 
			var copyThis:Litera=new Litera();
			copyThis.lockListen();
			copyThis.graphics.copyFrom(this.graphics);
			copyThis.width=avec.width;
			copyThis.height=avec.height;
			//var percent:int=0;
 
 
 
			var curr:BitmapData=new BitmapData(copyThis.width, copyThis.height,true, 0x22331122);
			curr.draw(copyThis, copyThis.transform.matrix);
			stage.addChild(new Bitmap(curr));		
		}
	}
}
copyThis я создаю, чтобы изменение размеров спрайта не отражалось на экране, мне нужно привести этот спрайт к ширине и высоте объекта avec.

Код AS3:
package  {
	public class Desk extends MovieClip {
 
		public function Desk() {
			// constructor code
		}
 
		public function drawStart(e:Event):void{
			stage.addEventListener(MouseEvent.MOUSE_MOVE, drawing);
		}
 
		public function drawStop(e:Event):void{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawing);
			f=true;
		}
 
		//рисование мелом
		private function drawing(e:MouseEvent):void{
			prevX=stage.mouseX;
			prevY=stage.mouseY;
			//если мел не выходит за границы доски
			if (stage.mouseX>this.x && stage.mouseX<(this.x+this.width)&& stage.mouseY>this.y && stage.mouseY<this.y+this.height){
					letter.graphics.lineStyle(5,0xFF992233);
					if (f) letter.graphics.moveTo(prevX, prevY);
					f=false;
					letter.graphics.lineTo(stage.mouseX, stage.mouseY);
			} else{
				f=true;
			}
		}
 
		var prevX, prevY:int;
		var f:Boolean=true;		
		var letter:Sprite=new Litera();
	}
}
Остальные классы в архиве, сдается мне, вся соль где-то в этих трех.

game.zip

Старый 25.02.2013, 21:27
GBee вне форума Посмотреть профиль Отправить личное сообщение для GBee Найти все сообщения от GBee
  № 2  
Ответить с цитированием
GBee
 
Аватар для GBee

Регистрация: Jan 2009
Сообщений: 3,067
Записей в блоге: 3
Отправить сообщение для GBee с помощью Skype™
Код AS3:
curr.draw(copyThis, copyThis.transform.matrix);
Попробуйте без матрицы.
__________________
Чтобы доказать, что вы не робот, причините вред другому человеку.

Старый 26.02.2013, 01:34
Toothbrusher вне форума Посмотреть профиль Отправить личное сообщение для Toothbrusher Найти все сообщения от Toothbrusher
  № 3  
Ответить с цитированием
Toothbrusher

Регистрация: Feb 2013
Сообщений: 11
Пробовала без матрицы, пробовала без copyThis работать напрямую с Litera через this. Ничего не работает, как надо. Объект Litera почему-то считает, что его this.x и this.y равны нулю, но при этом свои width и height он определяет правильно.

Старый 26.02.2013, 11:03
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 4  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
А потрейсите, чему равно
Код AS3:
trace(this.getBounds(this)); //это в литере
trace(copyThis.getBounds(copyThis)); // это там же, после копирования графики.
И еще вопрос:
Цитата:
Объект Litera почему-то считает, что его this.x и this.y равны нулю
Это какой объект? copyThis? Если да, то все правильно. Если нет, то чему они должны быть равны и почему?

Старый 26.02.2013, 18:30
Toothbrusher вне форума Посмотреть профиль Отправить личное сообщение для Toothbrusher Найти все сообщения от Toothbrusher
  № 5  
Ответить с цитированием
Toothbrusher

Регистрация: Feb 2013
Сообщений: 11
Цитата:
Сообщение от maxkar Посмотреть сообщение
А потрейсите, чему равно
Код AS3:
trace(this.getBounds(this)); //это в литере
trace(copyThis.getBounds(copyThis)); // это там же, после копирования графики.
У this'а и у копии эти значения равны. Вот, в первом случае это (x=48.5, y=48.5, w=181, h=210). (50,50) - это как раз начало доски. Во втором - (х=162, у=109, w=177, h=193). Путем прикладывания линейки к экрану и приблизительных вычислений выходит, что эти х и у от начала координат окна считаются. Вот, на скрине видно, что каляка заносится в растр лишь частично.
Нажмите на изображение для увеличения
Название: спрайт.JPG
Просмотров: 82
Размер:	25.0 Кб
ID:	29190
Цитата:
И еще вопрос:

Это какой объект? copyThis? Если да, то все правильно. Если нет, то чему они должны быть равны и почему?
да, copyThis. На мой взгляд, привязываться к родительским координатам должна крайняя верхняя правая точка литеры (точнее обрамляющего ее прямоугольника), а не какая-то далеко стоящая самого рисунка.

И еще вопрос: после того, как я сдвигаю куда-нибудь нарисованную литеру, а потом хочу ее дорисовать, рисующая линия возникает уже не под мелом, а где-то рядом с ним. Как это исправить, не возвращая литеру на прежнее место?

Старый 26.02.2013, 19:00
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 6  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
Ага, я сам тоже проверил. width и height дают фактические размеры контента. Копирование graphics никуда ничего в 0 не переносит, т.е. контент остается в тех же координатах (вычисление bounding box на самом деле далеко не самая простая операция, а вот копирование graphics - простая). Итого - матрицу нужно вручную делать. На самом деле это тривиально:
Код AS3:
  var copyThis:Litera=new Litera();
  copyThis.lockListen();
  copyThis.graphics.copyFrom(this.graphics);
 
  const bounds : Rectangle = copyThis.getBounds(copyThis);
  const a : Number = avec.width / bounds.width;
  const d : Number = avec.height / bounds.height;
  const trans : Matrix = new Matrix(a, 0, 0, d, -bounds.x, -bounds.y);
 
 
  var curr:BitmapData=new BitmapData(avec.width, avec.height,true, 0x22331122);
  curr.draw(copyThis, trans);
  stage.addChild(new Bitmap(curr));
Цитата:
Путем прикладывания линейки к экрану и приблизительных вычислений выходит, что эти х и у от начала координат окна считаются.
От (0, 0) спрайта (Litera). Вероятно, ее 0 находится около нуля (или в нуле) сцены. "0" - это точка привязки во Flash (вокруг нее повороты и т.п. делаются).

Цитата:
И еще вопрос: после того, как я сдвигаю куда-нибудь нарисованную литеру, а потом хочу ее дорисовать, рисующая линия возникает уже не под мелом, а где-то рядом с ним. Как это исправить, не возвращая литеру на прежнее место?
Два варианта решения. В обоих случаях нужно править Desk.drawing и учитывать в нем координаты Litera. Т.е. letter.graphics.lineTo будет не в state.mouseX, а в новые (корректированные) координаты. Первый способ - вручную вносить поправки относительно координат litera (т.е добавлять/вычитать litera.x/litera.y) . Второй - использовать globalToLocal:
Код AS3:
  const lpoint : Point = letter.globalToLocal(new Point(stage.mouseX, stage.mouseY));
  letter.graphics.lineTo(lpoint.x, lpoint.y);
P.S. Примеры не проверял, могут быть опечатки.

Старый 26.02.2013, 21:38
Toothbrusher вне форума Посмотреть профиль Отправить личное сообщение для Toothbrusher Найти все сообщения от Toothbrusher
  № 7  
Ответить с цитированием
Toothbrusher

Регистрация: Feb 2013
Сообщений: 11
Большое спасибо, it works! Только смещения bounds надо было еще домножить на а и d.
Код AS1/AS2:
new Matrix(a, 0, 0, d, -bounds.x*а, -bounds.y*d);
Жаль, конечно, что я пришла к этому путем перебора всех возможных значений и подстановки их во все возможные места, не понимая, что делаю. не комильфо, не по-программерски.

У меня тогда еще вопрос в общем по структуре программы: норм? Правильно ли размещать listener'ы в каждый в своих классах (как у меня) или лучше выносить их в тот класс, кот. будет управлять подключением/выключением? Но ведь тогда получится большая помойка из функций в Main'е. С другой стороны, listener'ов принято делать privat'ами, и если сторонний класс управляет подкл/выкл слушателей другого класса, то придется изменить доступ на public.
Где в целом можно посмотреть коды более-менее хороших и "соответствующих всем правилам и концепциям построения и всякое такое" игр, завязанных на программирование, а не на графику?

Старый 27.02.2013, 10:38
maxkar вне форума Посмотреть профиль Отправить личное сообщение для maxkar Найти все сообщения от maxkar
  № 8  
Ответить с цитированием
maxkar

Регистрация: Nov 2010
Сообщений: 497
Да, с матрицами поправка правильная. Действительно перемещения еще на масштаб нужно было домножить (потому что после масштаба перемещаться нужно меньше).

Цитата:
У меня тогда еще вопрос в общем по структуре программы: норм?
Лично мне не нравится, что на graphics в Litera рисование происходит из Desk при том, что сама Litera тоже активный объект. Все-таки в данном случае graphics - "чужая" собственность. Поэтому весь код по отрисовке (drawStart/drawStop/drawing) я бы перенес в Litera. Ну или слушатели оставил бы в desk, но методы отрисовки все-таки вызывал бы в литере. Тем более, что кроме litera (ну и stage) отрисовке больше ничего и не нужно. А вот startDragM/stopDragM можно бы и вынести из литеры - они по отношению к ней "внешние", ничем внутри нее не пользуются. Может быть, и compare частично из нее вынести (оставить в ней получение битмапки по требуемуому размеру (getBitmapImage(width: int, height: int)), а вот вывод - где-то во внешнем классе (main, наверное, хотя может быть и что-то другое).

Слушателей в данном случае можно размещать и в самих классах. Да и не только в этом. До тех пор, пока слушатель реализует неотъемлемое поведение самого объекта (по поводу неотъемлемости формальных критериев нет), он может размещаться в самом объекте. А вот если поведение от объекта "не зависит" или требует взаимодействия со "внешними" объектами, стоит использовать какой-то другой способ (или внешние слушатели, или свои события, или что-то еще).

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

Просто "смотреть" другой код обычно смысла не имеет. Нужно понимать, с какой целью этот код смотрится. Для сопровождения кода (когда он уже давно существует) важны два момента. Первый - навигация по коду. Она определяет, насколько легко найти нужное место (для внесения изменения/правки бага). Второй - собственно легкость внесения изменения (количество переделок, затронутых классов и т.п.). Поэтому обычно имеет смысл не просто смотреть код, а пытаться внести в него какие-то изменения. Можно даже какие-нибудь распространенные библиотеки взять вроде isolib/as3corelib и поиграться с "требованиями". А вдруг мы захотим делать не совсем то, что делает библиотека, а "немного по-другому". Например, поменять какой-то протокол обмена между клиентом/сервером, использовать картинки с прозрачностью вместо векторных и т.п.

Создать новую тему Ответ Часовой пояс GMT +4, время: 01:47.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 01:47.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.