Показать сообщение отдельно
Старый 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 Кб, 179 просмотров)