beTweenAS3

そろそろこのサンプルも終わりにしようかと思うんで、ゆらゆら動く部分の実装を解説しましょうかね。

動作サンプル(重いかもしれないんで別窓で)

サンプルファイル一式(Flash CS4形式)

最終的には上のようなものを作ります。
サンプルファイルは、きちんとクラス作ってますが、一応ココでの解説では、タイムラインコードで示します。
多分コピペすれば動くはず。

んで、このゆらゆら動くアニメーションには、BetweenAS3.bezierというメソッドを使います。
bezierといえば、こんな感じ。あとはここもいい感じの解説があります。

ただし、全てのパーティクルに対して個々にベジェ曲線を設定するわけにもいかんので、ベジェ曲線のコントロールポイントの数とか位置はランダムに取得するようにしたいのです。

//パーティクルのベジェの直径
var dist:int = 500;
//コントロールポイントの最大値、この変数に1を足した数が最大値になる。
var bezierMax:int = 10;
for (var i:int = 0 ; i < len ; i++) {
    //-----------
    //xzの基準位置を取得
    var centerX:int = particleArray[i].x;
    var centerZ:int = particleArray[i].z;
   
    //Tweenの最小値を計算
    var minX:int = centerX - dist / 2;
    var minZ:int = centerZ - dist / 2;
   
    //ベジェのコントロールポイントの数
    var countX:int = (Math.random() * bezierMax) + 2;
    var countZ:int = (Math.random() * bezierMax) + 2;
   
    //ベジェのコントロールポイントを格納する。
    var pointArrayX:Array = new Array();
    var pointArrayZ:Array = new Array();
    //ベジェを格納するオブジェクト
    var pointObj:Object = new Object();
   
    //ベジェのコントロールポイントを算出
    for (var forX:int = 0 ; forX < countX ; forX++) {
        pointArrayX.push( int(Math.random() * dist) + minX );
    }
    for (var forZ:int = 0 ; forZ < countZ ; forZ++) {
        pointArrayZ.push( int(Math.random() * dist) + minZ );
    }
   
    //Tweenの引数用のオブジェクト
    pointObj.x = pointArrayX;
    pointObj.z = pointArrayZ;

    var tweenXZ:IObjectTween = BetweenAS3.bezier(particleArray[i] , { x:centerX , z:centerZ } , null , pointObj , tweenTime , Linear.linear);
}

こんな感じで、bezierメソッドの第4引数にベジェのコントロールポイントを渡すのですが、ここの値はオブジェクト型を渡せばいいので、予めランダムな値の[x , y]というプロパティを持ったオブジェクトを作って、そいつを渡せば、ランダムなベジェ曲線のアニメーションを作ることができます。

その際に

//xzの基準位置を取得
var centerX:int = particleArray[i].x;
var centerZ:int = particleArray[i].z;
   
//Tweenの最小値を計算
var minX:int = centerX - dist / 2;
var minZ:int = centerZ - dist / 2;

こんな感じで、それぞれのプロパティの値を中心にして、コントロールポイントの範囲を決めてやります。

あとは、この処理を前回のエントリーのコードに移植してあげればOK。
てなわけで、タイムラインで動かす場合は下のコードををコピペしてみてくれ。

 import org.papervision3d.view.BasicView;
import org.papervision3d.materials.special.MovieAssetParticleMaterial;
import org.papervision3d.objects.special.ParticleField;
import org.papervision3d.cameras.CameraType;

import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Linear;
import org.libspark.betweenas3.events.TweenEvent;
import org.libspark.betweenas3.tweens.IObjectTween;
import org.libspark.betweenas3.tweens.ITween;


var world:BasicView = new BasicView(640 , 320 , true , false , CameraType.DEBUG);
var particleTweenArray:Array = new Array();

var mf:MovieAssetParticleMaterial = new MovieAssetParticleMaterial("test");
mf.smooth = true;

var fld:ParticleField = new ParticleField(mf , 200 , 1);

stage.addChild(world);
world.scene.addChild(fld);

world.startRendering();

fld.y = -500
world.camera.zoom = 50;

var tweenTime:int = 10;
var particleArray:Array = fld.particles;
var len:int = particleArray.length;

//--------------
//パーティクルのベジェの直径
var dist:int = 500;
//コントロールポイントの最大値、この変数に1を足した数が最大値になる。
var bezierMax:int = 10;
//--------------

var delay:Number = 0;
for (var i:int = 0 ; i < len ; i++) {
    particleArray[i].y = 0;
    
    //-----------
    //xzの基準位置を取得
    var centerX:int = particleArray[i].x;
    var centerZ:int = particleArray[i].z;
    
    //Tweenの最小値を計算
    var minX:int = centerX - dist / 2;
    var minZ:int = centerZ - dist / 2;
    
    //ベジェのコントロールポイントの数
    var countX:int = (Math.random() * bezierMax) + 2;
    var countZ:int = (Math.random() * bezierMax) + 2;
    
    //ベジェのコントロールポイントを格納する。
    var pointArrayX:Array = new Array();
    var pointArrayZ:Array = new Array();
    var pointObj:Object = new Object();
    
    //ベジェのコントロールポイントを算出
    for (var forX:int = 0 ; forX < countX ; forX++) {
        pointArrayX.push( int(Math.random() * dist) + minX );
    }
    for (var forZ:int = 0 ; forZ < countZ ; forZ++) {
        pointArrayZ.push( int(Math.random() * dist) + minZ );
    }
    
    //Tweenの引数用のオブジェクト
    pointObj.x = pointArrayX;
    pointObj.z = pointArrayZ;
    //-----------
    
    var tweenY:IObjectTween = BetweenAS3.tween(particleArray[i] , { y:2000} , null , tweenTime , Linear.linear);
    
    //-----------
    var tweenXZ:IObjectTween = BetweenAS3.bezier(particleArray[i] , { x:centerX , z:centerZ } , null , pointObj , tweenTime , Linear.linear);
    //-----------
    
    var tweenXYZ:ITween = BetweenAS3.parallel(tweenY , tweenXZ);
    tweenY.stopOnComplete = false;
 
    delay += 0.5;
   
    var delayTween:ITween = BetweenAS3.delay(tweenXYZ , delay);
    delayTween.play();
   
    particleTweenArray.push(tweenXYZ);
    delayTween.addEventListener(TweenEvent.COMPLETE , tweenCompFunc(i));
}
function tweenCompFunc(index:int):Function {
    return function(e:TweenEvent):void {
        particleTweenArray[index].play();
    }
}

アニメーションの話はまた次回~
とか書いておきながら、2ヶ月近く放置してしまったのだが・・・。

最終的には↓のような物を作ります。

動作サンプル(重いかもしれないんで別窓で)

サンプルファイル一式(Flash CS4形式)

前回はParticleFieldで生成されるパーティクルにアニメーションを適用させる方法までを解説しました。

今回は、それに味付けして、個々にアニメーションするようにして

こんなやつを作ってみましょう。

因みに、用意したサンプルのソースでは、ParticleFieldクラスのサブクラスとして実装しています。

まず、パーティクルのアニメーションをずらすには、「delay()」を使います。
前回のコードを、

var delay:Number = 0;
for (var i:int = 0 ; i < len ; i++) {
    particleArray[i].y = 0;
    var tweenY:IObjectTween = BetweenAS3.tween(particleArray[i] , { y:2000} , null , tweenTime , Linear.linear);
   
    var delayTween:ITween = BetweenAS3.delay(tweenY);
    delayTween.play();
}

とか書けば、一個一個ばらばらにアニメーションを開始すると思います。
この際のyの目標座標は、ParticleFieldのデフォルトの高さである2000に設定します。

前回は、fld.fieldHeightこうかきましたが、どうやらprivateらしく、実行したら、値にアクセスできませんでした。

んで、このままだとアニメーションが終わったら、終わったまんまになってしまうので、リピート再生させるために「stopOnComplete = false;」を設定してあげなくてはいけませんが、delayTweenのほうでリピート再生させると、ディレイ時間も反映させてしまうため、ものによっては、ディレイ時間が20秒とかになってしまいます。

なので、

var particleTweenArray:Array = new Array();
var delay:Number = 0;
for (var i:int = 0 ; i < len ; i++) {
    particleArray[i].y = 0;
    var tweenY:IObjectTween = BetweenAS3.tween(particleArray[i] , { y:2000} , null , tweenTime , Linear.linear);
    tweenY.stopOnComplete = false;
   
    var delayTween:ITween = BetweenAS3.delay(tweenY);
    delayTween.play();

    particleTweenArray.push(tweenY);
    delayTween.addEventListener(TweenEvent.COMPLETE , tweenCompFunc(i));

}
function tweenCompFunc(index:int):Function {
    return function(e:TweenEvent):void {
        particleTweenArray[index].play();
    }
}

こんな風に書き換えます。

ディレイを与えたムービーが終わったら、リピート再生になっているtweenYのほうを再生開始するように設定します。

次回はゆらゆら動くようなアニメーションをつけてみます。

因みに、タイムラインコードとして書く場合の全てのコードは

import org.papervision3d.view.BasicView;
import org.papervision3d.materials.special.MovieAssetParticleMaterial;
import org.papervision3d.objects.special.ParticleField;
import org.papervision3d.cameras.CameraType;

import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Linear;
import org.libspark.betweenas3.events.TweenEvent;
import org.libspark.betweenas3.tweens.IObjectTween;
import org.libspark.betweenas3.tweens.ITween;


var world:BasicView = new BasicView(640 , 320 , true , false , CameraType.DEBUG);
var particleTweenArray:Array = new Array();

var mf:MovieAssetParticleMaterial = new MovieAssetParticleMaterial("test");
mf.smooth = true;

var fld:ParticleField = new ParticleField(mf , 200 , 1);

stage.addChild(world);
world.scene.addChild(fld);

world.startRendering();

fld.y = -500
world.camera.zoom = 50;

var tweenTime:int = 10;
var particleArray:Array = fld.particles;
var len:int = particleArray.length;

var delay:Number = 0;
for (var i:int = 0 ; i < len ; i++) {
    particleArray[i].y = 0;
    var tweenY:IObjectTween = BetweenAS3.tween(particleArray[i] , { y:2000} , null , tweenTime , Linear.linear);
    tweenY.stopOnComplete = false;
  
    delay += 0.5;
   
    var delayTween:ITween = BetweenAS3.delay(tweenY , delay);
    delayTween.play();
   
    particleTweenArray.push(tweenY);
    delayTween.addEventListener(TweenEvent.COMPLETE , tweenCompFunc(i));
}
function tweenCompFunc(index:int):Function {
    return function(e:TweenEvent):void {
        particleTweenArray[index].play();
    }
}

プロフィール

HN.NoBody

NoBody

市ヶ谷のとあるオフィスでFlashクリエイターとして労役中。
なんとなくチーフ。

twitterでつぶやき中