[AS3]俺俺TweenエンジンOreOreTweenを作ってみよう1

2010/07/1

こんにちは。きんくまです。

ご報告なのですが、先月のこのサイトのページビューがついに93000[ページ/月]になりました!
一度もはてブにホットエントリすることもなく、地味な記事ばかりなのですが、
9万越えを達成したのも、ひとえに皆様のおかげです。ありがとうございます!
次の目標は大台の10万ページビューです。がんばります。

近況です。
この間からようやく本腰いれてObjective-CというかiPhone/iPadアプリ開発もやりはじめまして。
なんとかいろいろとわかってきました。
役立ち情報などをもう少しためてから、ブログに書いていきたいと思います。

さて、本題です。今回から何度かにわたって俺俺Tweenエンジンを作っていきたいと思います。
ちまたにはTweenerやBetweenAS3、Tweensy、kTweenなどすばらしいTweenエンジンが
あるんですが、そこまで及ばなくても100コぐらいのTweenなら大丈夫!ぐらいのゆるいエンジンを
作りたいと思います。

今回つくったもの

Tweenエンジンって結局何

時間のあるかたはとりあえず、城戸さんの講義がわかりやすいと思います。

GEEKs in OSAKA
Flash モーションプログラミング + 大阪てら子

自分の理解としては、「Tweenエンジンは、始点と終点の値を分割したもの」だと思いました。

例えば、始点0、終点100の値をTweenするとします。
分割数を10としたとき、0,10,20,30,40,50,60,70,80,90,100となり、
分割数が5であれば、0,20,40,60,80,100となります。

それで、これらの分割した値を使って、タイマーやEnterframeの中でSpriteやMovieClipに
都度適用していくことで、パラパラアニメのように動いているように見える。というわけです。

城戸さんの講義ではパラメータtを使って、分割していました。
tは0 <= t <= 1 の範囲で動くパラメータです。 dtという値を考えます。 dtは分割数に応じて変化する値で、分割数が10なら 1 / 10 = 0.1、分割数が5なら 1 / 5 = 0.2となります。 さきほどの0から100までをtを使って分割すると iを0から分割数までの変数として、tに応じた値valueはこんな感じになります。 t = dt * i; value = (100 - 0) * t + 0; valueの最後に0をたしているのは初期値が例えば20のときには value = (100 - 20) * t + 20; となるためです。 そんで、一番上に作ったデモの場合にあてはめると(実際のコードでは分割数を30にしてますが、図のために5にしてます) こんな感じになります。 tween1_fig1

今回のコード

■Main

package 
{
	import com.bit101.components.PushButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author KinkumaDesign
	 */
	[SWF(width="450",height="450",backgroundColor="0x000000",frameRate="30")]
	public class Main extends Sprite 
	{
		public var ball:Circle;
		public var startBtn:PushButton;
		
		public const START_POS:Point = new Point(50, 150);//開始地点
		public const END_POS:Point = new Point(400, 150);//終了地点
		
		public var tweenValues:Array;
		public var tweenCount:int;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			ball = new Circle(20, 0x1ECAE8);
			addChild(ball);
			ball.setPosition(START_POS.x, START_POS.y);
			
			startBtn = new PushButton(this, 180, 330, "start", startBtnClickHD);
		}
		
		private function startBtnClickHD(e:MouseEvent):void
		{
			tweenValues = OreOreTween.getTweenValues(END_POS.x, START_POS.x);
			trace(tweenValues); //各地点
			
			//tweenスタート
			startBtn.visible = false;
			tweenCount = 0;
			addEventListener(Event.ENTER_FRAME, updateTween);
		}
		
		private function updateTween(e:Event):void 
		{
			//tween終了
			if (tweenCount == tweenValues.length) 
			{
				removeEventListener(Event.ENTER_FRAME, updateTween);
				startBtn.visible = true;
			//tween値を適用
			}else {
				var value:Number = tweenValues[tweenCount];
				ball.x = value;
				tweenCount++;
			}
		}
		
	}
	
}

■OreOreTween

package  
{
	import flash.geom.Point;
	/**
	 * ...
	 * @author KinkumaDesign
	 */
	public class OreOreTween
	{
		public static function getTweenValues(to:Number, from:Number):Array
		{
			var values:Array = [];

			var segmentNum:Number = 30; //分割数
			var i:int;
			var t:Number;
			var dt:Number = 1 / segmentNum; //分割数
			var value:Number;
			for (i = 0; i <= segmentNum; i++) {
				t = dt * i; //tは0以上1以下の範囲で動く
				value = (to - from) * t + from;
				values.push(value); 
			}
			return values;
		}
	}
}

■Circle

package  
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.geom.Point;
	/**
	 * ...
	 * @author KinkumaDesign
	 */
	public class Circle extends Sprite
	{
		
		public function Circle(radius:Number = 5, color:int = 0, alpha:Number = 1) 
		{
			var g:Graphics = this.graphics;
			g.beginFill(color, alpha);
			g.drawCircle(0, 0, radius);
			g.endFill();
		}
		
		public function setPosition(posX:Number, posY:Number):void
		{
			x = posX;
			y = posY;
		}
	}

}

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る