Flash Player 11 3次ベジェ曲線cubicCurveTo

なにかと騒がれているFlash Player 11ですが、3次ベジェ曲線cubicCurveToを試してみました。

Flash Player 11 3次ベジェ曲線cubicCurveTo – wonderfl build flash online

折角なのでBezierSegmentと重ねて書いていました。
雑感としてポイントを多くするとcubicCurveToの方が早いです。
cubicCurveToは引数が6個と多めで気が滅入りそうですが、座標しか入りませんしbezierSegment同様の順番なのですぐに慣れるでしょう。
ただし、cubicCurveToは描写だけですから座標は取れません。
「ベジェ曲線上を動く」などのはBezierSegmentなどを使うことになるでしょう。

Get Adobe Flash player

[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のことですからすぐに崩れそうですが。