Показать сообщение отдельно
Старый 30.01.2014, 12:03
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 12  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
если устроит не совсем элипс, а скорее овал из кривых, то с помощью безьевых утилит Дембицкого можно
Код AS3:
package
{
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Bezier;
	import flash.geom.Point;
 
 
	public class Main extends Sprite
	{
		private var ball:Circle = new Circle(30);
		private var segments:Array = [];
		private var cX:Number = 300;
		private var cY:Number = 300;
		private var rX:Number = 200;
		private var rY:Number = 100;
 
 
		private var mX:Number;
		private var mY:Number;
 
		public function Main():void
		{
 
			ball.x = cX;
			ball.y = cY;
			addChild(ball);
 
			graphics.lineStyle(2);
 
			// типа 'элипс' из четырех безье
			for (var i:int = 0; i < 4; i++)
			{
				var a:Number = Math.PI * i / 2;
 
				var sP:Point = new Point(cX + Math.cos(a) * rX, cY + Math.sin(a) * rY);
				a += 0.5 * Math.PI;
				var eP:Point = new Point(cX + Math.cos(a) * rX, cY + Math.sin(a) * rY);
				var cP:Point = i % 2 ? new Point(eP.x, sP.y) : new Point(sP.x, eP.y);
				var segm:Bezier = new Bezier(sP, cP, eP);
				segments.push(segm);
 
				if (!i) graphics.moveTo(sP.x, sP.y);
				graphics..curveTo(cP.x, cP.y, eP.x, eP.y);
 
			}
 
			ball.addEventListener(MouseEvent.MOUSE_DOWN, ball_mouseDown);
 
		}
 
		private function ball_mouseDown(e:MouseEvent):void
		{
			mX = stage.mouseX;
			mY = stage.mouseY;
			stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
 
		}
 
		private function stage_mouseUp(e:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
		}
 
		private function stage_mouseMove(e:MouseEvent):void
		{
			// двигаем
			ball.x += stage.mouseX - mX;
			ball.y += stage.mouseY - mY;
			mX = stage.mouseX;
			mY = stage.mouseY;
 
 
			// проверка и коррекция
			var dir:Number = Math.PI + Math.atan2(cY - ball.y, cX - ball.x);
			var segm:Bezier = segments[Math.floor(2 * dir / Math.PI) % 4];
 
			var t:Number = segm.getClosest(new Point(ball.x, ball.y));
			var tP:Point = segm.getPoint(t);
 
			if (Point.distance(new Point(ball.x, ball.y), tP) < ball.radius)
			{
				dir = Math.atan2(tP.y - ball.y, tP.x - ball.x);
				ball.x = tP.x - ball.radius * Math.cos(dir);
				ball.y = tP.y - ball.radius * Math.sin(dir);
			}
		}
 
	}
 
}
 
import flash.display.Sprite;
 
class Circle extends Sprite
{
 
	public var radius:Number;
 
	public function Circle(r:Number)
	{
		super();
		radius = r;
		graphics.beginFill(0x808080);
		graphics.drawCircle(0, 0, r);
 
	}
}
Добавлено через 35 минут
а можно и не связываться с безье, а строить просто отрезками и брать ближайший по наименьшему расстоянию, тогда и эллипс будет как эллипс
Код AS3:
package
{
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
 
	import flash.geom.Point;
 
 
	public class Main extends Sprite
	{
		private var ball:Circle = new Circle(30);
		private var segments:Array = [];
		private var cX:Number = 300;
		private var cY:Number = 300;
		private var rX:Number = 200;
		private var rY:Number = 100;
 
		private var mX:Number;
		private var mY:Number;
 
		public function Main():void
		{
 
			ball.x = cX;
			ball.y = cY;
			addChild(ball);
 
			graphics.lineStyle(2);
 
			// элипс из отрезков
			var n:Number = 60;
			var dA:Number = 2 * Math.PI / n;
			var a:Number = 0;
			for (var i:int = 0; i < n; i++)
			{
 
				var sP:Point = new Point(cX + Math.cos(a) * rX, cY + Math.sin(a) * rY);
				a += dA;
				var eP:Point = new Point(cX + Math.cos(a) * rX, cY + Math.sin(a) * rY);
				var mid:Point = Point.interpolate(sP, eP, 0.5);
 
				segments.push(mid);
 
				if (!i) graphics.moveTo(sP.x, sP.y);
				graphics.lineTo(eP.x, eP.y);
 
			}
 
			ball.addEventListener(MouseEvent.MOUSE_DOWN, ball_mouseDown);
 
		}
 
		private function ball_mouseDown(e:MouseEvent):void
		{
			mX = stage.mouseX;
			mY = stage.mouseY;
			stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
 
		}
 
		private function stage_mouseUp(e:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
		}
 
		private function stage_mouseMove(e:MouseEvent):void
		{
			// двигаем
			ball.x += stage.mouseX - mX;
			ball.y += stage.mouseY - mY;
			mX = stage.mouseX;
			mY = stage.mouseY;
 
			// проверка и коррекция
			var tP:Point;
			var min:Number = Number.MAX_VALUE;
			for (var i:int = 0; i < segments.length; i++) 
			{
				var d:Number = Point.distance(new Point(ball.x, ball.y), segments[i]);
				if ( d< min)
				{
					tP = segments[i];
					min = d;
				}
			}
 
			var dir:Number = Math.PI + Math.atan2(cY - ball.y, cX - ball.x);
			if (Point.distance(new Point(ball.x, ball.y), tP) < ball.radius)
			{
				dir = Math.atan2(tP.y - ball.y, tP.x - ball.x);
				ball.x = tP.x - ball.radius * Math.cos(dir);
				ball.y = tP.y - ball.radius * Math.sin(dir);
			}
		}
 
	}
 
}
 
import flash.display.Sprite;
 
class Circle extends Sprite
{
 
	public var radius:Number;
 
	public function Circle(r:Number)
	{
		super();
		radius = r;
		graphics.beginFill(0x808080);
		graphics.drawCircle(0, 0, r);
 
	}
}