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

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

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

Регистрация: Jul 2013
Адрес: Днепр
Сообщений: 529
Отправить сообщение для alexandrratush с помощью ICQ Отправить сообщение для alexandrratush с помощью Skype™
По умолчанию Эффект пластики с отменой

Здравствуйте! Задача: создать эффект пластики с возможностью отмены последнего результата.
Сама реализация эффекта была позаимствована отсюда silin.su/AS3/bitmap/plasticDistort/

Изучив код, вроде понял что к чему, но вот вернуть корректно предыдущее состояние "пластики" не выходит.
К примеру: 3 раза взяли и потянули мишкой, потом нажали "отмена" (все отлично происходит), и если опять начинаем "тянуть" картинку, то состояние сетки опять стает как до первого нажатия "отмена" + только что "потянули" (демо версия и исходник в CS5 приложена).

Весь код собран в один класс, опишу кратко на что, по моему, стоит обратить внимание:
1. Сохранение текущего слепка в массив истории происходит в ф-ции savePlastic
2. Возврат - в undoPlastic

Код AS3:
package {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.ui.*;
	import fl.controls.NumericStepper;
	import fl.controls.CheckBox;
	import fl.controls.Button;
 
 
	public class Main extends Sprite {
		// Компоненты
		private var _numStepper:NumericStepper;
		private var _gridCheckBox:CheckBox;
		private var _btnReset:Button;
		private var _btnUndo:Button;
 
		//
		private var divX:int = 30;
		private var divY:int = 40;
		//
		private var W:Number = 300;
		private var H:Number = 400;
		//
		private var _canvas:Sprite;
 
		private var indices:Vector.<int>;
		private var uvData:Vector.<Number>;
		private var verticies:Vector.<Number>;
		private var nodes:Vector.<Point>;
 
		private var _texture:BitmapData;
 
		private var anchor:Point = new Point();
		private var marker:Point = new Point();
 
		private var _plasticArrHistory:Array;
 
 
		public function Main():void {
			_plasticArrHistory = new Array();
 
			// картинка
			_texture = new TestBD();
 
			// Добавляем контейнер
			_canvas = new Sprite();
			addChild(_canvas);
 
			// Инициализация компонентов
			initComponents();
 
			initGrid();
 
			// Отрисовка
			draw();
 
			// Слушатели
			_canvas.addEventListener(MouseEvent.MOUSE_DOWN, canvasMouseDown);
			_canvas.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
			_canvas.addEventListener(MouseEvent.ROLL_OVER, canvasRollOver);
			_canvas.addEventListener(MouseEvent.ROLL_OUT, canvasRollOut);
		}
 
		/** Инициализация компонентов */
		private function initComponents():void {
			_numStepper = numStepper;
			_numStepper.addEventListener(Event.CHANGE, update);
 
			_gridCheckBox = gridCheckBox;
 
			_btnReset = btnReset;
			_btnReset.addEventListener(MouseEvent.CLICK, btnResetClick);
 
			_btnUndo = btnUndo;
			_btnUndo.addEventListener(MouseEvent.CLICK, btnUndoClick);
		}
 
		private function canvasRollOut(e:MouseEvent):void {
			Mouse.cursor = MouseCursor.AUTO;
		}
 
		private function canvasRollOver(e:MouseEvent):void {
			Mouse.cursor = MouseCursor.HAND;
		}
 
		/** Обработчик нажатия миши */
		private function canvasMouseDown(e:MouseEvent):void {
			anchor.x = marker.x = mouseX;
			anchor.y = marker.y = mouseY;
 
			_canvas.addEventListener(MouseEvent.MOUSE_MOVE, canvasMouseMove);
		}
 
		/** Обработчик перемещения миши */
		private function canvasMouseMove(e:MouseEvent):void {
			marker.x = mouseX;
			marker.y = mouseY;
			update();
			anchor.x = marker.x;
			anchor.y = marker.y;
		}
 
		/** Обработчик отпускания миши */
		private function stageMouseUp(e:MouseEvent):void {
			_canvas.removeEventListener(MouseEvent.MOUSE_MOVE, canvasMouseMove);
 
			// Сохраняем состояние
			savePlastic();
		}
 
		/** Сохранение состояния */
		public function savePlastic():void {
			var v:Vector.<Number> = verticies.concat();
			var n:Vector.<Point> = nodes.concat();
 
			// Сохраняем состояние в массив
			_plasticArrHistory.push( {v:v, n:n} );
		}
 
		/** Шаг назад в пластике */
		public function undoPlastic():void {
			var len:int = _plasticArrHistory.length;
 
			// Если нету сохраненных состояний, то ...
			if (len == 0) return;
 
			// Срезаем последнее состояние в истории
			_plasticArrHistory.length -= 1;
 
			// Если сохраненных состояний больше чем 1
			if (len != 1) {
				// Получаем последнее состояние (перед срезом это было предпоследнее)
				len = _plasticArrHistory.length;
				var v:Vector.<Number> = _plasticArrHistory[len - 1].v;
				var n:Vector.<Point> = _plasticArrHistory[len - 1].n;
 
				// Пересохраняем значения
				verticies = v.concat();
				nodes = n.concat();
 
				// Отрисовка
				draw();
				resampleGrid();
			} else {
				// Если 1 значение, то просто сброс сетки
				resetGrid();
			}
		}
 
		private function btnResetClick(e:MouseEvent):void {
			resetGrid();
		}
 
		private function btnUndoClick(e:MouseEvent):void {
			undoPlastic();
		}
 
		private function update(e:Event = null):void {
			resampleGrid();
			draw();
		}
 
		private function draw():void {
			_canvas.graphics.clear();
 
			if (_gridCheckBox.selected) {
				_canvas.graphics.lineStyle(0, 0x80FF80, 0.35);
			}
 
			_canvas.graphics.beginBitmapFill(_texture, null, false, true);
			_canvas.graphics.drawTriangles(verticies, indices, uvData);
			_canvas.graphics.endFill();
		}
 
		private function initGrid():void {
			uvData = new Vector.<Number>();
			verticies = new Vector.<Number>();
			indices = new Vector.<int>();
			nodes = new Vector.<Point>();
 
			var k:int = 0;
			for (var i:int = 0; i <= divY; i++) {
				for (var j:int = 0; j <= divX; j++) {
					verticies.push(W * j / divX, H * i / divY);
					uvData.push(j / divX, i / divY);
 
					if (i < divY && j < divX) {
						indices.push(k, k + 1, k + divX + 1, k + 1, k + divX + 2, k + divX + 1);
					}
					nodes.push(new Point(W * j / divX, H * i / divY));
					k++;
				}
			}
		}
 
		private function resampleGrid():void {
			for (var i:int = 1; i < divY; i++) {
				for (var j:int = 1; j < divX; j++) {
 
					var k:int = i * (divX + 1) + j;
					var node:Point = nodes[k];
					var fX:Number = (anchor.x - node.x < 0) ? ((W - node.x) / (W - anchor.x)) : (node.x / anchor.x);
					var fY:Number = (anchor.y - node.y < 0) ? ((H - node.y) / (H - anchor.y)) : (node.y / anchor.y);
					var f:Number = fX * fY;
 
					for (var m:int = 1; m < _numStepper.value; m++) {
						f *= f;
					}
 
					node.x += (marker.x - anchor.x) * f;
					node.y += (marker.y - anchor.y) * f;
					verticies[2 * k] = node.x;
					verticies[2 * k + 1] = node.y;
				}
			}
		}
 
		private function resetGrid():void {
			for (var i:int = 0; i <= divY; i++) {
				for (var j:int = 0; j <= divX; j++) {
					var k:int = i * (divX + 1) + j;
					nodes[k].x = W * j / divX;
					nodes[k].y = H * i / divY;
				}
			}
 
			update();
		}
 
	}
}
Помогите решить данную проблему.
Спасибо!

Исходник:
flasher.rar

Демка:
Main.swf   (82.7 Кб)
Вложения
Тип файла: swf Main.swf (82.7 Кб, 176 просмотров)

Старый 05.05.2014, 21:04
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 2  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
не возьмусь сказать, что конкретно косячит в вашем примере, но явно что-то с сохранением узлов в массиве точек (nodes который), он вообще в этом раскладе избыточный (у меня был приплетен ради выпендрежа с твином)
вот "отшкуренный' от лишних деталей вариант, может поможет разобраться

Код AS3:
package
{
 
	import com.bit101.components.*;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
 
	public class PlasticDeform extends Sprite
	{
 
		private var divX:int = 30;
		private var divY:int = 40;
 
		private var W:Number = 300;
		private var H:Number = 400;
 
		private var indices:Vector.<int>;
		private var uvData:Vector.<Number>;
		private var verticies:Vector.<Number>;
 
		[Embed(source="sample.jpg")]
		private var sample_jpg:Class;
 
		private var texture:BitmapData=Bitmap(new sample_jpg()).bitmapData;
 
		private var gridCheckBox:CheckBox;
		private var undoBut:PushButton;
 
 
		private var mX:Number;
		private var mY:Number;
 
		private var canvas:Sprite = new Sprite();
 
		private var undoList:Array = [];
 
 
		public function PlasticDeform():void
		{
 
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
 
 
 
			addChild(canvas);
			gridCheckBox = new CheckBox(this, 20, 420, "grid", draw);
			undoBut = new PushButton(this, 160, 420, "undo", undoBut_click);
 
			initGrid();
			draw();
 
			canvas.addEventListener(MouseEvent.MOUSE_DOWN, canvas_mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
 
		}
 
		private function canvas_mouseDown(e:MouseEvent):void
		{
			mX = mouseX;
			mY = mouseY;
 
 
			canvas.addEventListener(MouseEvent.MOUSE_MOVE, canvas_mouseMove);
			undoList.push(verticies.concat());
 
		}
 
		private function canvas_mouseMove(e:MouseEvent):void
		{
 
			for (var k:int = 0; k < verticies.length; k += 2)
			{
				var tX:Number = verticies[k];
				var tY:Number = verticies[k + 1];
				var fX:Number = (mX - tX < 0) ? ((W - tX) / (W - mX)) : (tX / mX);
				var fY:Number = (mY - tY < 0) ? ((H - tY) / (H - mY)) : (tY / mY);
				var f:Number = fX * fY;
				f *= f;
 
				verticies[k] += (mouseX - mX) * f;
				verticies[k + 1] += (mouseY - mY) * f;
			}
			draw();
			mX = mouseX;
			mY = mouseY;
 
		}
 
		private function stage_mouseUp(e:MouseEvent):void
		{
			canvas.removeEventListener(MouseEvent.MOUSE_MOVE, canvas_mouseMove);
		}
 
		private function undoBut_click(e:Event = null):void
		{
 
			if (undoList.length)
			{
				verticies = undoList.pop();
				draw();
			}
 
		}
 
		private function draw(e:Event = null):void
		{
 
			canvas.graphics.clear();
			if (gridCheckBox.selected)
			{
				canvas.graphics.lineStyle(0, 0x80FF80, 0.35);
			}
			canvas.graphics.beginBitmapFill(texture, null, false, true);
			canvas.graphics.drawTriangles(verticies, indices, uvData);
			canvas.graphics.endFill();
 
		}
 
		private function initGrid():void
		{
 
			uvData = new Vector.<Number>();
			verticies = new Vector.<Number>();
			indices = new Vector.<int>();
 
			var k:int = 0;
			for (var i:int = 0; i <= divY; i++)
			{
				for (var j:int = 0; j <= divX; j++)
				{
 
					verticies.push(W * j / divX, H * i / divY);
					uvData.push(j / divX, i / divY);
					if (i < divY && j < divX)
					{
						indices.push(k, k + 1, k + divX + 1, k + 1, k + divX + 2, k + divX + 1);
					}
 
					k++;
				}
			}
 
		}
 
	}
 
}

grid.swf   (36.5 Кб)
Вложения
Тип файла: swf grid.swf (36.5 Кб, 152 просмотров)

Старый 05.05.2014, 22:30
alexandrratush вне форума Посмотреть профиль Отправить личное сообщение для alexandrratush Найти все сообщения от alexandrratush
  № 3  
Ответить с цитированием
alexandrratush
 
Аватар для alexandrratush

Регистрация: Jul 2013
Адрес: Днепр
Сообщений: 529
Отправить сообщение для alexandrratush с помощью ICQ Отправить сообщение для alexandrratush с помощью Skype™
Спасибо огромное, переделал все под ваш пример и все заработало.
Почему не работало у меня, нет времени разбираться.
Еще раз спасибо!

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

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

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


 


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


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