2013年6月20日 星期四

用FLASH AS3 製作Cardano Wheel軌跡圖教學

        如果小圓半徑是大圓半徑的1/2,小圓沿著大圓內側滾動一圈,小圓上的一點滾動的軌跡會是一條直線,小圓內部的一點滾動的軌跡則會是一個橢圓形,小圓圓心滾動的軌跡則會是一個圓形。

 
      以下是Action Script 3 的原始程式碼,有興趣學習AS3的同好可一起研究......
先匯入要使用的類
import flash.display.Graphics;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;

製作標題文字
var titleText_txt:TextField=new TextField();
var titleText_fmt:TextFormat = new TextFormat();
titleText_fmt.color=0x0000FF;
titleText_fmt.align=TextFormatAlign.CENTER;
titleText_fmt.size=40;
titleText_txt.defaultTextFormat=titleText_fmt;
titleText_txt.autoSize= TextFieldAutoSize.CENTER;
titleText_txt.x = stage.stageWidth / 2 ;titleText_txt.y = 20;
titleText_txt.text="CARDANO WHEEL";
addChild(titleText_txt);  將標題文字加到舞臺上
 
宣告要使用的物件名稱
var bigCircle:Shape = new Shape();  宣告大圓為一個Shape的顯示物件
var rollCircle:Sprite= new Sprite();   宣告小圓為一個SPrite的顯示物件,以方便加入markPoint物件
var markPoint:Shape= new Shape(); 宣告一個小圓的子物件作為要滾動的定點var 
centerTrace:Shape= new Shape();  宣告一個Shape物件作為要圓心滾動軌跡的繪圖容器var
bordTrace:Shape= new Shape();   宣告一個Shape物件作為要圓上一點滾動軌跡的繪圖容器var 
inerTrace:Shape= new Shape();   宣告一個Shape物件作為要圓內一點滾動軌跡的繪圖容器var 
CENTER_X=stage.stageWidth/2,CENTER_Y=stage.stageHeight/2,RADIUS=150; 定義大圓的中心位置及半徑

繪製大圓
bigCircle.graphics.beginFill(0x00ff00,0.3);  設定綠色填充,Alpha值為30%bigCircle.graphics.lineStyle(3,0x00ffff,1);   設定線條寬度為3,Alpha值為100%
bigCircle.graphics.drawCircle(0,0,RADIUS); 在bigCircle上繪製大圓,圓心在左上角
bigCircle.graphics.endFill();
bigCircle.x=CENTER_X;             將大圓圓心移到舞台中央
bigCircle.y=CENTER_Y;
addChild(bigCircle);        在舞臺台上顯示bigCircle

繪製內部滾動的小圓
rollCircle.graphics.beginFill(0x0000ff,0.3);
rollCircle.graphics.lineStyle(2,0x0000ff,0.5);
圓心位置放在(RADIUS/(Math.SQRT2*2),RADIUS/(Math.SQRT2*2)),使圓周通過左上角的註冊點(0,0)

rollCircle.graphics.drawCircle(RADIUS/(Math.SQRT2*2),RADIUS/(Math.SQRT2*2),RADIUS/2);
rollCircle.graphics.endFill();
rollCircle.graphics.beginFill(0x000000,1);
rollCircle.graphics.lineStyle(1,0x000000,1);
rollCircle.graphics.drawCircle(RADIUS/(Math.SQRT2*2),RADIUS/(Math.SQRT2*2),2);   繪製圓心rollCircle.graphics.endFill();
rollCircle.x=CENTER_X;   將小圓左上角註冊點位置移到大圓的圓心
rollCircle.y=CENTER_Y;
addChild(rollCircle);
繪製小圓上另兩個要觀察的動點,註冊點位置為左上角
markPoint.graphics.lineStyle(2,0x0000ff,1); 圓周上以藍色標示markPoint.graphics.beginFill(0x0000ff,1);
markPoint.graphics.drawCircle(RADIUS/2,0,2); 位置放在圓周上
markPoint.graphics.lineStyle(1,0x0000ff,1);
markPoint.graphics.beginFill(0x0000ff,1);
markPoint.graphics.drawCircle(-RADIUS/2,0,2); 位置放在圓周上
markPoint.graphics.lineStyle(1,0xff0000,1);
markPoint.graphics.beginFill(0xff0000,1);
markPoint.graphics.drawCircle(RADIUS/4,0,2);  位置放在圓內上
markPoint.graphics.endFill();
markPoint.x=RADIUS/(Math.SQRT2*2);  markPoint左上角註冊點位置移到小圓的圓心
markPoint.y=RADIUS/(Math.SQRT2*2); 
markPoint.rotation=45;     旋轉45度,和小圓相對於大圓的角度一致
rollCircle.addChild(markPoint); 將小圓顯示在舞台上

定義一個Point物件來記錄小圓圓心在舞台上的坐標 
var tracePoint1:Point=rollCircle.localToGlobal(new Point(RADIUS/(Math.SQRT2*2),RADIUS/(Math.SQRT2*2)));  
centerTrace.graphics.moveTo(tracePoint1.x,tracePoint1.y);  將記錄圓心軌跡的容器centerTrace繪圖點移到小圓圓心
addChild(centerTrace);   將centerTrace顯示在舞台上

定義第二個Point物件來記錄小圓圓周上的點在舞台上的坐標
var tracePoint2:Point=markPoint.localToGlobal(new Point(- RADIUS/2,0));
bordTrace.graphics.moveTo(tracePoint2.x,tracePoint2.y);
addChild(bordTrace);

定義第三個Point物件來記錄小圓圓內的點在舞台上的坐標
var tracePoint3:Point=markPoint.localToGlobal(new Point(RADIUS/4,0));
inerTrace.graphics.moveTo(tracePoint3.x,tracePoint3.y);
addChild(inerTrace);

設定計時器來執行滾劫
var myTimer=new Timer(100,360);   宣告計時器物件,每1/10秒動作一次,共執行360次
var i:int=0;
myTimer.addEventListener(TimerEvent.TIMER,roundTimer);  註冊計時器偵聽事件到事件處理程序roundTimer
myTimer.start();  計時器開始動作
function roundTimer(event:TimerEvent):void {      計時器偵聽到動作事件的處理程序 
rollCircle.rotation+=1;   小圓繞左上角(大圓圓心)旋轉1度
 markPoint.rotation-=2;  markPoint繞左上角(小圓圓心)旋轉-2度
 var tracePointTemp1:Point=rollCircle.localToGlobal(new Point(RADIUS/(Math.SQRT2*2),RADIUS/(Math.SQRT2*2)));    記錄旋轉後圓心的新位置 centerTrace.graphics.lineStyle(2,0x000000,1);
 centerTrace.graphics.lineTo(tracePointTemp1.x,tracePointTemp1.y);  將原來的點和新點連接起來
 tracePoint1=tracePointTemp1;   新點置換前一點,以便下一次連接
 var tracePointTemp2:Point=markPoint.localToGlobal(new Point(- RADIUS/2,0)); 記錄旋轉後圓周上的點的新位置
 bordTrace.graphics.lineStyle(2,0x0000ff,1);
 bordTrace.graphics.lineTo(tracePointTemp2.x,tracePointTemp2.y);
 tracePoint2=tracePointTemp2;
 var tracePointTemp3:Point=markPoint.localToGlobal(new Point(RADIUS/4,0));  記錄旋轉後圓內的點的新位置
 inerTrace.graphics.lineStyle(2,0xff0000,1);
 inerTrace.graphics.lineTo(tracePoint3.x,tracePoint3.y);
 tracePoint3=tracePointTemp3;
}

沒有留言:

張貼留言