なにかと騒がれているFlash Player 11ですが、3次ベジェ曲線cubicCurveToを試してみました。
Flash Player 11 3次ベジェ曲線cubicCurveTo – wonderfl build flash online
折角なのでBezierSegmentと重ねて書いていました。
雑感としてポイントを多くするとcubicCurveToの方が早いです。
cubicCurveToは引数が6個と多めで気が滅入りそうですが、座標しか入りませんしbezierSegment同様の順番なのですぐに慣れるでしょう。
ただし、cubicCurveToは描写だけですから座標は取れません。
「ベジェ曲線上を動く」などのはBezierSegmentなどを使うことになるでしょう。
[sourcecode language=”as3″]
package
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Point;
	import fl.motion.BezierSegment;
	/**
	 * …
	 * @author pc98
	 */
	public class Main extends Sprite
	{
		private static var bezierParts:uint = 20;
		private static var coordinateMember:uint = 3;
		//
		private var coordinateList:Array;
		private var bezierSegmentFlag:Boolean = true;
		private var cubicCurveToFlag:Boolean = true;
		private var coordinate_sp:Sprite;
		public function Main():void
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		public static function get getBezierParts():uint
		{
			return bezierParts;
		}
		public static function get getCoordinateMember():uint
		{
			return coordinateMember;
		}
		private function init(event:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			//
			coordinate_sp = new Sprite();
			addChild(coordinate_sp);
			coordinate_sp.visible = false;
			setCoodinate(coordinateMember);
			var contoroller:Controller = new Controller();
			addChild(contoroller);
			contoroller.init();
			contoroller.addEventListener(ContorollerEvent.SHOCK_CLICK, shockListener);
			contoroller.addEventListener(ContorollerEvent.CUBIC_CLICK, cubicCurveToListener);
			contoroller.addEventListener(ContorollerEvent.BEZIER_CLICK, bezierSegmentListener);
			contoroller.addEventListener(ContorollerEvent.BEZIER_SLIDER, bezierSliderListener);
			contoroller.addEventListener(ContorollerEvent.COORDINATE_SLIDER, coordinateSliderListener);
			contoroller.addEventListener(ContorollerEvent.POINTVISIBLE_CLICK, pointvisibleListener);
			//
			addEventListener(Event.ENTER_FRAME, enterFrameListener);
			stage.addEventListener(Event.RESIZE, resizeLisntener);
			/*
			var test_sp:Sprite = new Sprite();
			addChild(test_sp);
			var g:Graphics = test_sp.graphics;
			g.lineStyle(6, 0);
			g.moveTo(100, 100);
			g.cubicCurveTo(200, 100, 200, 200, 300, 200);
			g.curveTo(400,200,400,300);
			*/
		}
		private function resizeLisntener(event:Event):void
		{
			coordinate_sp.removeChildren();
			setCoodinate(coordinateMember);
		}
		private function pointvisibleListener(event:ContorollerEvent):void
		{
			coordinate_sp.visible = coordinate_sp.visible?false:true;
		}
		private function coordinateSliderListener(contorollerEvent:ContorollerEvent):void
		{
			coordinate_sp.removeChildren();
			setCoodinate(contorollerEvent.value);
		}
		private function bezierSliderListener(contorollerEvent:ContorollerEvent):void
		{
			bezierParts = contorollerEvent.value;
		}
		private function setCoodinate(value:uint):void
		{
			coordinateMember = value;
			coordinateList = [];
			var i:uint;
			var n:uint = coordinateMember;
			for (i = 0; i < n;i++){
				var coordinate:Coordinate = new Coordinate();
				coordinate_sp.addChild(coordinate);
				coordinate.init();
				coordinateList.push(coordinate);
			}
			shockListener();
		}
		private function shockListener(event:ContorollerEvent=null):void
		{
			var i:uint;
			var n:uint = coordinateList.length;
			for (i = 0; i < n; i++) {
				var coordinate:Coordinate = coordinateList[i];
				coordinate.shock();
			}
		}
		private function cubicCurveToListener(event:ContorollerEvent):void
		{
			cubicCurveToFlag = cubicCurveToFlag?false:true;
		}
		private function bezierSegmentListener(event:ContorollerEvent):void
		{
			bezierSegmentFlag = bezierSegmentFlag?false:true;
		}
		private function enterFrameListener(event:Event):void
		{
			var g:Graphics = this.graphics;
			g.clear();
			var c0:Coordinate;
			var h0:Sprite;
			var p1:Point;
			var p0:Point;
			var c1:Coordinate;
			var h1:Sprite;
			var p2:Point;
			var p3:Point;
			var i:uint;
			var j:uint;
			var n:uint = coordinateList.length;
			var m:uint = bezierParts;
			var coordinatePoint:Point;
			var point:Sprite;
			if (cubicCurveToFlag) {
				g.lineStyle(5, 0xFF0000);
				c0 = coordinateList[0];
				point = c0.getPoint;
				g.moveTo(point.x, point.y);
				for (i = 0; i < n ;i++){
					c0 = coordinateList[i];
					h0 = c0.getRightHandle;
					//
					if(i==n-1){
						c1 = coordinateList[0];
					}else {
						c1 = coordinateList[i + 1];
					}
					h1 = c1.getLeftHandle;
					point = c1.getPoint;
					//
					g.cubicCurveTo(h0.x, h0.y, h1.x, h1.y, point.x, point.y);
				}
			}
			if (bezierSegmentFlag) {
				g.lineStyle(1, 0x0000FF);
				for (i = 0; i < n ;i++){
					c0 = coordinateList[i];
					point = c0.getPoint;
					h0 = c0.getRightHandle;
					p0 = new Point(point.x, point.y);
					p1 = new Point(h0.x , h0.y);
					if(i==n-1){
						c1 = coordinateList[0];
					}else {
						c1 = coordinateList[i + 1];
					}
					h1 = c1.getLeftHandle;
					point = c1.getPoint;
					p2 = new Point(h1.x, h1.y);
					p3 = new Point(point.x, point.y);
					//
					var bizier:BezierSegment = new BezierSegment(p0, p1, p2, p3);
					g.moveTo(p0.x, p0.y);
					for (j = 1; j <= m; j++) {
						coordinatePoint = bizier.getValue(j / m);
						g.lineTo(coordinatePoint.x, coordinatePoint.y);
					}
				}
			}
		}
	}
}
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
class Coordinate extends Sprite
{
	private const K:Number = 0.1;
	private const U:Number = 0.06;
	//
	private var vx:Number = 0;
	private var vy:Number = 0;
	private var w:Number = 0;
	//
	private var rightHandle:Sprite;
	private var leftHandle:Sprite;
	private var point:Sprite;
	//
	private var d:Number;
	private var theta:Number;
	private var v_angular:Number = 0;
	private var angular:Number = 0;
	private var targetX:Number;
	private var targetY:Number;
	private var isDrag:Boolean = false;
	private var isHandleDrag:Boolean = false;
	//
	public function Coordinate()
	{
	}
	public function get getPoint():Sprite
	{
		return point;
	}
	public function get getRightHandle():Sprite
	{
		return rightHandle;
	}
	public function get getLeftHandle():Sprite
	{
		return leftHandle;
	}
	public function init():void
	{
		d = 50 + 50 * Math.random();
		theta = 2 * Math.PI * Math.random();
		point = new Sprite();
		setPoint(point, 5);
		point.addEventListener(MouseEvent.MOUSE_DOWN, pointMouseDownLisnter);
		targetX =
		point.x = 100+(stage.stageWidth-200)*Math.random();
		targetY =
		point.y = 100+(stage.stageHeight-200)*Math.random();
		//
		rightHandle = new Sprite();
		setPoint(rightHandle, 3);
		leftHandle = new Sprite();
		setPoint(leftHandle, 3);
		//
		rightHandle.addEventListener(MouseEvent.MOUSE_DOWN, rightMouseDownListener);
		leftHandle.addEventListener(MouseEvent.MOUSE_DOWN, leftMouseDownListener);
		//
		setHandlePosition();
		drawLines();
		//
		addEventListener(Event.ENTER_FRAME, enterFrameListener);
		//
		addEventListener(Event.REMOVED_FROM_STAGE, removeFromStageListener);
	}
	private function setPoint(handle:Sprite,radius:Number):void
	{
		var g:Graphics = handle.graphics;
		handle.buttonMode = true;
		g.beginFill(0);
		g.drawCircle(0, 0, radius);
		addChild(handle)
	}
	private function removeFromStageListener(event:Event):void
	{
		removeEventListener(Event.REMOVED_FROM_STAGE, removeFromStageListener);
		//
		point.removeEventListener(MouseEvent.MOUSE_DOWN, pointMouseDownLisnter);
		rightHandle.removeEventListener(MouseEvent.MOUSE_DOWN, rightMouseDownListener);
		leftHandle.removeEventListener(MouseEvent.MOUSE_DOWN, leftMouseDownListener);
		removeEventListener(Event.ENTER_FRAME, enterFrameListener);
	}
	private function enterFrameListener(event:Event):void
	{
		if (isDrag) {
			targetX =
			point.x = mouseX;
			targetY =
			point.y = mouseY;
		}else {
			var ax:Number = K * (targetX – point.x);
			vx += ax – U * vx;
			point.x += vx;
			var ay:Number = K * (targetY – point.y);
			vy += ay – U * vy;
			point.y += vy;
		}
		//
		if (!isHandleDrag) {
			var aw:Number = K * (0 – angular);
			v_angular += aw – U * v_angular;
			angular += v_angular;
			setHandlePosition();
			drawLines();
		}
	}
	private function setHandlePosition():void
	{
		rightHandle.x = point.x + d * Math.cos(theta+angular);
		rightHandle.y = point.y + d * Math.sin(theta+angular);
		leftHandle.x = point.x + d * Math.cos(theta +angular+ Math.PI);
		leftHandle.y = point.y + d * Math.sin(theta +angular+ Math.PI);
	}
	public function shock():void
	{
		var a:Number = 5 + 45 * Math.random();
		var theta:Number = 2 * Math.random();
		vx += a * Math.cos(theta);
		vy += a * Math.sin(theta);
		//
		v_angular = 0.5*Math.PI – 1*Math.PI*Math.random();
	}
	private function pointMouseDownLisnter(event:MouseEvent):void
	{
		isDrag = true;
		stage.addEventListener(MouseEvent.MOUSE_UP, pointMouseUpListener);
	}
	private function pointMouseUpListener(event:MouseEvent):void
	{
		isDrag = false;
		stage.removeEventListener(MouseEvent.MOUSE_UP, pointMouseUpListener);
	}
	private function leftEnterFrameListener(event:Event):void
	{
		dragingHandleEnterFrameLisntener(leftHandle,Math.PI);
	}
	private function drawLines():void
	{
		var g:Graphics;
		g = this.graphics;
		g.clear();
		g.lineStyle(1, 0);
		g.moveTo(rightHandle.x, rightHandle.y);
		g.lineTo(leftHandle.x, leftHandle.y);
	}
	private function dragingHandleEnterFrameLisntener(handle:Sprite,deltaTheta:Number):void
	{
		d = Math.sqrt(Math.pow(handle.x – point.x, 2) + Math.pow(handle.y – point.y, 2));
		theta = deltaTheta + Math.atan2(handle.y – point.y, handle.x – point.x);
		//
		setHandlePosition();
		drawLines();
	}
	private function mouseUpListener(event:MouseEvent):void
	{
		isHandleDrag = false;
		leftHandle.stopDrag();
		rightHandle.stopDrag();
		removeEventListener(Event.ENTER_FRAME, leftEnterFrameListener);
		removeEventListener(Event.ENTER_FRAME, rightEnterFrameListener);
		stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
		//
	}
	private function rightMouseDownListener(event:MouseEvent):void
	{
		v_angular = 0;
		angular = 0;
		isHandleDrag = true;
		rightHandle.startDrag();
		addEventListener(Event.ENTER_FRAME, rightEnterFrameListener);
		stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
	}
	private function leftMouseDownListener(event:MouseEvent):void
	{
		isHandleDrag = true;
		leftHandle.startDrag();
		addEventListener(Event.ENTER_FRAME, leftEnterFrameListener);
		stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
	}
	private function rightEnterFrameListener(event:Event):void
	{
		dragingHandleEnterFrameLisntener(rightHandle,0);
	}
}
import com.bit101.charts.LineChart;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.Slider;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import net.hires.debug.Stats;
class Controller extends Sprite
{
	private var coordinateLabel:Label;
	private var bezierLabel:Label;
	public function Controller()
	{
	}
	public function init():void
	{
		var parts:uint;
		parts = Main.getCoordinateMember;
		coordinateLabel = new Label();
		addChild(coordinateLabel);
		coordinateLabel.text = "points number : " + parts ;
		coordinateLabel.x = 80;
		coordinateLabel.y = 20;
		var coordinateSlider:Slider = new Slider();
		addChild(coordinateSlider);
		coordinateSlider.x = 80;
		coordinateSlider.y = 10;
		coordinateSlider.width = 150;
		parts = Main.getCoordinateMember;
		coordinateSlider.setSliderParams(2, 500, parts);
		coordinateSlider.addEventListener(Event.CHANGE,coordinateSliderListener);
		var stats:Stats = new Stats();
		addChild(stats);
		//
		parts = Main.getBezierParts;
		bezierLabel = new Label();
		addChild(bezierLabel);
		bezierLabel.text = "BezierSegments : " +parts;
		bezierLabel.x = 240;
		bezierLabel.y = 20;
		//
		var bezierSlider:Slider = new Slider();
		addChild(bezierSlider);
		bezierSlider.x = 240;
		bezierSlider.y = 10;
		bezierSlider.width = 150;
		bezierSlider.setSliderParams(1, 30, parts);
		bezierSlider.addEventListener(Event.CHANGE, bezierSilderListener);
		//
		var cubicCurveToBtn:PushButton = new PushButton();
		cubicCurveToBtn.x = 80;
		cubicCurveToBtn.y = 40;
		cubicCurveToBtn.width = 150;
		addChild(cubicCurveToBtn);
		cubicCurveToBtn.label = "cubicCurveTo(red line)";
		cubicCurveToBtn.addEventListener(MouseEvent.CLICK, cubicCurveToListener);
		//
		var BezierSegmentBtn:PushButton = new PushButton();
		BezierSegmentBtn.x = 240;
		BezierSegmentBtn.y = 40;
		BezierSegmentBtn.width = 150;
		addChild(BezierSegmentBtn);
		BezierSegmentBtn.label = "BezierSegment(blue line)";
		BezierSegmentBtn.addEventListener(MouseEvent.CLICK, bezierSegmentListener);
		//
		var shockBtn:PushButton = new PushButton();
		addChild(shockBtn);
		shockBtn.x = 80;
		shockBtn.y = 70;
		shockBtn.width = 150;
		shockBtn.label = "shake";
		shockBtn.addEventListener(MouseEvent.CLICK, shockListener);
		//
		var pointVisibleBtn:PushButton = new PushButton();
		addChild(pointVisibleBtn);
		pointVisibleBtn.x = 240;
		pointVisibleBtn.y = 70;
		pointVisibleBtn.width = 150;
		pointVisibleBtn.label = "Point Visible";
		pointVisibleBtn.addEventListener(MouseEvent.CLICK, pointLisntener);
	}
	private function pointLisntener(event:MouseEvent):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.POINTVISIBLE_CLICK);
		dispatchEvent(contorollerEvent);
	}
	private function coordinateSliderListener(event:Event):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.COORDINATE_SLIDER);
		var parts:uint = Math.floor(event.currentTarget.value);
		contorollerEvent.value =  parts;
		coordinateLabel.text = "points points : " + parts ;
		dispatchEvent(contorollerEvent);
	}
	private function bezierSilderListener(event:Event):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.BEZIER_SLIDER);
		var parts:uint = Math.floor(event.currentTarget.value);
		contorollerEvent.value =  parts;
		bezierLabel.text = "BezierSegments : " +parts;
		dispatchEvent(contorollerEvent);
	}
	private function shockListener(event:MouseEvent):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.SHOCK_CLICK);
		dispatchEvent(contorollerEvent);
	}
	private function cubicCurveToListener(event:MouseEvent):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.CUBIC_CLICK);
		dispatchEvent(contorollerEvent);
	}
	private function bezierSegmentListener(event:MouseEvent):void
	{
		var contorollerEvent:ContorollerEvent = new ContorollerEvent(ContorollerEvent.BEZIER_CLICK);
		dispatchEvent(contorollerEvent);
	}
}
import flash.events.Event;
class ContorollerEvent extends Event
{
	public var value:Number = 0;
	public static const BEZIER_CLICK:String = "bezier_click";
	public static const CUBIC_CLICK:String = "cubic_click";
	public static const SHOCK_CLICK:String = "shock_click";
	public static const BEZIER_SLIDER:String = "bezier_slider";
	public static const COORDINATE_SLIDER:String = "coordinate_slider";
	public static const POINTVISIBLE_CLICK:String = "pointvisible_click";
	public function ContorollerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
	{
		super(type, bubbles, cancelable);
	}
	public override function clone():Event
	{
		return new ContorollerEvent(type, bubbles, cancelable);
	}
	public override function toString():String
	{
		return formatToString("ContorollerEvent", "type", "bubbles", "cancelable", "eventPhase");
	}
}
[/sourcecode]
あと、cubicCurveToとcurveToの混在も出来ます。
[sourcecode language=”as3″]
g.moveTo(100, 100);
g.cubicCurveTo(200, 100, 200, 200, 300, 200);
g.curveTo(400,200,400,300);
[/sourcecode]
次期Flashで、ペンツールで混在もできたら面白そうですね。
Flashのことですからすぐに崩れそうですが。

