3Dを描画する(5)〜オブジェクトを動かす

3Dを描画する(5)〜オブジェクトを動かす

今回は前回まで作成した3Dの球体を動かしてみましょう。

説明はいいからやり方を教えろという方への手順です。

  1. 前回までの方法で作成した3Dの球体のソースを用意します。
  2. addEventListenerでENTER_FRAMEイベントを待ち受けて リスナー関数を実行する。
  3. リスナー関数で球体を動かす処理を行う。

 

3D球体を動かすソース

package 
{
    import org.papervision3d.objects.primitives.*;
    import org.papervision3d.view.*;
    import org.papervision3d.materials.*;
    import flash.events.Event

    public class Main4 extends BasicView
    {

        public function Main4():void 
        {
            var sphere:Sphere = new Sphere(null,60,10,10);
            scene.addChild(sphere);
            stage.addEventListener(Event.ENTER_FRAME, onmove);
            var houkou:int =1;
            function onmove ():void {
                sphere.x += 10 * houkou;
                sphere.rotationY += 10 ;
                if (sphere.x < 0 || sphere.x > stage.stageWidth) {
                    houkou *= -1;
                }
            }
            startRendering();
        }       
    }   
}

ここから文法の説明です。

addEventListenerとは

stage.addEventListener(Event.ENTER_FRAME, onmove);

「インスタンスbox_mcをクリックしたらtest()を実行する」といったインタラクティブ(対話式)な処理を考えたとき、この中には「1どこで、2何が起きたら、3どうする」の3つの要素が含まれています。このイベント処理をスクリプトではaddEventListener()というメソッドを使って設定します。書式は次のようになります。イベントが発生するオブジェクトに対して、イベントタイプとリスナー関数をペアにしてイベントリスナーとして追加します。

イベントターゲット.addEventListener(イベントタイプ,リスナー関数)
addEventListenerの引数は正確には次のとおりですが簡単なイベント処理を行うには第2引数まで指定して後は省略する場合があります。その他の引数の意味については別途特集で解説します。
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false)

イベントについてはイベントの概念資料をこちらのPDFで参照ください。

ENTER_FRAMEについて

ENTER_FRAMEは繰り返し発生するイベントです。フレームレートに合わせて繰り返し発生するフレーム再生イベントは、アニメーションで利用する繰り返しイベントとして最適なイベントです。デフォルトのフレームレートは毎秒12フレームなので、デフォルトのENTER_FRAMEの頻度は毎秒12回になります。

リスナー関数

function onmove ():void {
        sphere.x += 10 * houkou;
        sphere.rotationY += 10 ;
        if (sphere.x < 0 || sphere.x > stage.stageWidth) {
        houkou *= -1;
}

sphere.x += 10 * houkou;はもう少し親切に書くとsphere.x = sphere.x + 10 * houkou;となります。物理運動の等速運動を行う動きはsphere.x += 10の部分で表されます。ENTER_FRAMEが発生するごとに10ピクセルだけ右に動くという意味です。
ちなみに、sphere.y += 10ではy軸に対して下に10ピクセル動くという意味になります。

sphere.rotationY += 10 ;はy軸を基準に時計回りに回転をさせています。地球の自転と逆の動きですね。

* houkouは方向を決めます。
if (sphere.x < 0 || sphere.x > stage.stageWidth)
if文でx軸が0またはステージの右側を出てしまったらという条件を表しています。 そしてその条件にあてはまったらhoukou *= -1にするというステートメントになっています。
マイナス1を積算することで動きを逆にするわけです。

ところで、このソースで動かしてみるとなんだか小さな範囲で動いています。if文の条件と違うと思いませんか。
実はこれはカメラの設定に原因があります。 trace(camera);を最後に入れてカメラの設定をトレースしてみるとx:0 y:0 z:-1000 という結果がでてきます。つまり明示的にカメラの設定を書かなければデフォルトのカメラの設定が使用されています。で、カメラの位置がx:0 y:0 z:-1000となっている訳です。
カメラの位置を明示的に示したい場合はstartRendering();の前にcamera.z = -500;などのように指定します。

camera.z = -500;
startRendering();

円周運動させるにはsin、cosを使います。参考ソースです。

package 
{
    import org.papervision3d.objects.primitives.*;
    import org.papervision3d.view.*;
    import org.papervision3d.materials.*;
    import flash.events.Event

    public class Main5 extends BasicView
    {

        public function Main5():void 
        {

            var angle:Number = 0;
            var radius:Number = 600;
            var angleChange:Number = 5;
            var centerX:Number = stage.stageWidth/2;
            var centerY:Number = stage.stageHeight/2;

            var sphere:Sphere = new Sphere(null,60,10,10);
            scene.addChild(sphere);
            addEventListener(Event.ENTER_FRAME, onmove);
            function onmove ():void {
                var radian:Number = deg2rad(angle);
                sphere.x = centerX + radius * Math.cos(radian);
                sphere.y = centerY + radius / 3 * Math.sin(radian);
                sphere.rotationY = 10;
                angle += angleChange;
                angle %= 360;
            }

            function deg2rad(deg:Number):Number {
                return deg * (Math.PI/180)
            }
            startRendering();
        }

    }

}