こんにちは。きんくまです。
ご報告なのですが、先月のこのサイトのページビューがついに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にしてます)
こんな感じになります。

今回のコード
■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;
}
}
}