Home > Flash/Flex
Web 酒 肴
[Flex][ActionScript]くるくる回るローディング(読み込み中)画像をFlexで
- 2008-09-21 (Sun)
- Flash/Flex , ActionScript
Flexアプリケーションから画像やその他の少し大きなファイルを読み込んだり、もしくはサーバに少し時間のかかるリクエストを送るとき、よくあるアニメーションGIFのローディング画像を使おうと思った。 だけど、どうやらFlex標準のImageコンポーネントはアニメーションGIFに対応していないらしい。 対応しているライブラリもどこかが提供しているようだが、ローディング画像のためだけに他のライブラリをダウンロードさせるのも嬉しくない。
ということで、くるくる画像を生成・表示するActionScriptクラスを作った。 以下のように呼び出せば簡単にできる。
//ローディング画像オブジェクト生成
var loading:LoadingPicture = new LoadingPicture(画像サイズ, バーの数, バーの太さ, バーの長さ, 開始色, 終了色, バーのスタイル);
//ローディング画像表示
loading.show(親オブジェクト, X座標, Y座標);
//ローディング画像の回転開始
loading.start();
ローディング画像オブジェクト生成時のパラメータにどのような値を入れればどうなるのか、それは下のサンプルを色々いじってもらえばわかると思います。
ソースはこちら。
[Flex][ActionScript]PDFビューアのようにマウスドラッグでスクロールする方法
- 2008-08-23 (Sat)
- Flash/Flex , ActionScript
以下のように画像などのウィンドウ内のコンテンツをマウスでドラッグしてスクロールする方法。
Flexではこの処理が組み込まれているコンテナが無いように思う。 ということで仕方なしに自分で実装することに。
試行錯誤しながらなかなかうまくいかず、めんどくさいなぁ・・・と思ってたら、めちゃくちゃ簡単だった。 ポイントはたった1つ。
よく考えたらこれ、ドラッグじゃないじゃない
「じゃないじゃない」とかよくわからん言葉を使ってしまったが、要はドラッグではないだろう、ということ。 ドラッグってのはマウスの操作に従って、画像なりコンポーネントの座標を別の座標に変更すること。 で、よくよく考えたら、このドラッグでスクロールってのは画像の座標は変わってない。 常に (x, y) = (0, 0) のまま。
動いてるのはスクロールバーだけ
ってことだったのです。 ということがわかれば後は簡単。 以下の方針にしたがってチョコチョコっとコーディングするだけでした。
- 画像上でのMOUSE_DOWNとMOUSE_UPのイベントを監視
- MOUSE_DOWNするとMOUSE_MOVEのイベントの監視をスタート
- MOUSE_MOVE時は前回のマウスカーソルの場所と、今回のマウスカーソルの位置の差(つまり移動量)を取得
- パネルのスクロールバーの位置に上記の移動量を減算する
ポイントはスクロールバーはマウスカーソルとは反対の動きをしなくてはいけないので、移動量を加算ではなく減算するということ。 ドラッグしたまま画面からカーソルがはみ出たりした場合の処理はまだ入れてないが、そのあたりを調整すればこれで十分だと思う。
なんとなくドラッグだという固定観念から離れられずに時間を喰ってしまった。 こんなにも簡単にできるのか。コードもとっても短いです。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="289" height="350" applicationComplete="init()">
<mx:Script>
<![CDATA[
private var preMouseX:Number;
private var preMouseY:Number;
private function init():void{
img.addEventListener(MouseEvent.MOUSE_DOWN, imageDragStart);
img.addEventListener(MouseEvent.MOUSE_UP, imageDragEnd);
}
private function imageDragStart(event:MouseEvent):void{
preMouseX = mouseX;
preMouseY = mouseY;
img.addEventListener(MouseEvent.MOUSE_MOVE, imageMove);
}
private function imageDragEnd(event:MouseEvent):void{
img.removeEventListener(MouseEvent.MOUSE_MOVE, imageMove);
}
private function imageMove(event:MouseEvent):void{
panel.horizontalScrollPosition -= mouseX - preMouseX;
panel.verticalScrollPosition -= mouseY - preMouseY;
preMouseX = mouseX;
preMouseY = mouseY;
}
]]>
</mx:Script>
<mx:Panel id="panel" x="0" y="0" width="289" height="350" layout="absolute">
<mx:Image id="img" source="@Embed('animation.jpg')" buttonMode="true" x="0" y="0"/>
</mx:Panel>
</mx:Application>
Flex入門者がアニメーションを基礎から説明してみる #7(最終回)
- 2008-08-10 (Sun)
- ActionScript , Flash/Flex
突然ですがこの「Flex入門者がアニメーションを基礎から説明してみる」の連載は今回で終了とします。 なぜかというと学習している書籍の内容的に1、2回のエントリーで書ききれるものが尽きてしまったからです。 本当はここから以下のようなものに話は及びます。
キネマティクス
人体の腕や足のように、関節を持った部品どうしが関連を持って運動する
3Dの基本
奥行きのある空間を平面上に表します。RPGゲームの3Dダンジョンのようなことができます。
3Dの応用
物体を立体的に表現し、そこに照明を当てて影などをつけます。 まだ読んでないので正確には理解してませんが。
これらのことをブログに書こうと思ったら、一つの話題を理解しやすく書くのに5回程度のエントリーを必要としそうです。 そしてそれは書籍をそのまま転載することとあまり差がなくなってしまいそうな気がするので、僕の望むところではありません。
まとめとして
最終回は新しいことを解説しません。 今まで解説してきたことの中でメインとなっていた、物体を現実と同じように運動させる方法についてのまとめを書きます。
僕がボールを使用して解説した運動は以下のものです。
等速直線運動
一番基本的な運動です。力を加えたらそっちの方に飛んで行く、もしくは転がっていく。
反射
主に壁に跳ね返ったときに使用しました。 反射する障害物に角度があるとき、すなわち外壁ではなく斜めになっている壁などに反射させるには少し高度な応用が必要です。僕は解説していませんが、書籍には1章割いて解説があります。
落下運動
これは等加速度運動の一例でした。宇宙空間のロケットの噴射にも応用できます。
摩擦
ボールが転がり続けたり、跳ね返り続けないための処置です。 現実世界は常に摩擦があるので、これを行わないと自然な動きになりません。
バネ
これは重力の応用です。 重力は常に同じ力が下に加わっていますが、バネはバネの始点に向かって、離れているほど強い加速度が加わります。
一つずつ解説
さて、あなたがここでの例のようにボールなどをリアルに運動させようとしたとき、まず行うべきは「等速直線運動」の処理を実装することです。 具体的に言うと、以下の2つを用意するのです。
等速直線運動の実装
X方向の速度とY方向の速度をフィールドで宣言する
このようにします。 最初は固定で適当な値を入れてもいいでしょう。
private var vx:Number; //X方向の速度 private var vy:Number; //Y方向の速度単位時間ごとに速度を位置に加算する
Flexの場合はENTER_FRAMEイベントにリスナ関数をセットして、フレーム毎に実行される関数内で速度を物体の位置に加算します。 ballというオブジェクトが表示されているのであれば以下のようにします。
private function onEnterFrame(event:Event):void{ ball.x += vx; ball.y += vy; }
これだけでボールは同じ方向に向かって進み続けるでしょう。 これ自体はとっても簡単ですが、このとっても簡単なことはいつも変わらないし、あとの仕事はさらにシンプルなのです。
壁の反射、重力、バネ、摩擦などの実装
色々なサンプルを掲載してきましたが、やっていることにはある共通点があります。 それはいじるのは速度だけということです。 壁の外にはみ出たときなど、特殊な例でない限り、物体のX座標やY座標はいじりません。 常に速度を適切な場所で少し変更するだけで、これらは実現できるのです。 一つずつ解説していきましょう。
壁の反射
物体が移動することにより、壁との衝突を検知した時点で速度を反転させるだけです。 つまり、横の壁に衝突したら
vx *= -1;します。縦の壁に衝突したらvy *= -1;です。 たったこれだけ。重力
単位時間ごとつまりENTER_FRAMEのリスナ関数内で速度に重力の影響を加算します。 上のonEnterFrame関数に以下の一行を加えるような感じです。
private function onEnterFrame(event:Event):void{ ball.x += vx; ball.y += vy; vy += gravity; //gravityは重力の作用を表す数値(0.1などを代入しておく) }摩擦
摩擦とは常に速度を0に近づけるので、速度に一定の値を単位時間ごとにかけるだけです。 上のサンプルだと以下の2行を加えます。
private function onEnterFrame(event:Event):void{ ball.x += vx; ball.y += vy; vy += gravity; //gravityは重力の作用を表す数値(0.1などを代入しておく) vx *= friction; //frictionは摩擦を表す数値(0.95などを代入しておく) vy *= firction; }
バネの解説は前回やったため割愛します。 どうでしょうか?とてもシンプルではないですか? 実際に完成させるにはもう少し色々な処理を考える必要がありますが、基本的にはこれでいけます。
そしてこれらは、必要なものだけを取捨選択して書き加えればよいのです。 例えばビリヤード台を上から見た図なら、等速直線運動と反射、摩擦を実装する。しかし重力はいらないから実装しない、とか。 バネと重力はいるけど、摩擦は実装せずにずっとビヨンビヨン動かしておこう、とか。 自分の作りたい世界に合わせて、必要なものだけを書き加えるという実にシンプルな作り方ができるのです。
さらに、ここで解説していない処理を加えるとしても、多くの場合は既存のコードに修正はほとんどいりません。 その処理に必要な操作を、「速度」に対して行うだけでいいのです。そういえばボールをドラッグで掴んで投げた処理もそうでした。 とっても複雑な処理も、実は一つずつの処理を順番に実行している場合がほとんどなのです。
どうですか?簡単でしょう? 多くの人がアニメーションの簡単さ、楽しさに気付いてくれることを期待しています。 もちろん、もっともっと複雑なことがやりたい人は、簡単なことばかりでは済まないないでしょう。 その場合でも、この本さえあれば、きっと糸口は見つかります。
また宣伝かよ、とか思ったそこのあなた。だから初めからそうだと言ってるじゃないですか。
では皆さん、楽しいアニメーション作成を。
Flex入門者がアニメーションを基礎から説明してみる #6
- 2008-08-05 (Tue)
- ActionScript , Flash/Flex
今回はバネです。ていうかFlexBuilderの試用期間があと10日に迫ってまいりました。あと10日で連載終了などできるわけもなく・・・・・・買うしかないか・・・。それともフリーのFlashDeveloper使うかな?いや、ここは大人しく購入しておくのがいいだろう。
だって買ったら頑張って使わなきゃ元取れないし!
だから頑張れるし!!
摩擦で速度を抹殺せよ!!
夜は恥ずかしいダジャレがためらうことなく口から出てきます。
まあそれはいいとして、前回作成したコードに修正を加えます。 あのままだと、ボールは最終的に転がりつづけたままなかなか止まりません。 壁に反射したときに速度は少し減少しているので、そのうち止まりますが、現実世界には摩擦というものがあります。 摩擦とは、いついかなるときも、速度を0に近づけているものです。
ということでonEnterFrame関数の中で、常に速度に摩擦を適用すればよさそうです。 ここで大事なのは「速度を0に近づける」ということ。 重力のように一定値を引くのではありません。
例えば速度3→1になるのは速度が2減少しています。 では速度が1のときは?同じように2減少させると-1になってしまいます。 これでは反対側に飛んでいくだけなので、摩擦で物体が停止しようとしているときの動作ではありません。
正解は1以下の数値をかけるのです。これで速度は一定して弱まり続けて最終的に0に限りなく近づきます。 フィールド変数として摩擦を表す定数を宣言しましょう。
//摩擦による速度の低下
public var friction:Number = 0.98;
次に、この定数をonEnterFrame関数の最後でX, Y方向の速度にそれぞれ乗じます。
//摩擦の考慮
vx *= friction;
vy *= friction;
これでどうなりますか? 今までよりずっと本物らしくなったでしょう。 摩擦をよりリアルに再現しようとすると、もっと複雑な計算が必要なのですが、手軽さと結果のバランスを考えるとこれくらいが最適な方法だと考えられます。
いよいよバネ!
いや~長かった。 それではバネの動きを実装しましょう。
まず、バネの端っこはもちろんこのボールに繋げるわけですが、もう片方の端も固定しなければなりません。 そこでバネのもう一つの端を画面の真ん中に設定します。 フィールド変数で以下のように宣言しましょう。
//バネの中心点
public var springX:Number = stage.stageWidth / 2;
public var springY:Number = stage.stageHeight / 2;
次に、ボールの真ん中と、バネの中心点が繋がっているように線を描写する関数を作っておきます。
private function drawSpring():void{
//画面の中心に円の描画
graphics.clear();
graphics.beginFill(0);
graphics.drawCircle(springX, springY, 5);
graphics.endFill();
//ボールと画面の中心を線でつなぐ
graphics.lineStyle(2, 0);
graphics.moveTo(ball.x, ball.y);
graphics.lineTo(springX, springY);
}
そしてバネの力をボールの運動に反映させます。 この場合はどのように考えたらいいのでしょうか。
まず、バネは常にボールをある力で引っ張ります。常に引っ張るということはボールの速度に常に影響を与え続けるということです。 ということは重力と同じようにonEnterFrame関数内で、速度に対して何らかの処理をすればいいということですね。 速度に何をしたらいいのでしょうか。ポイントは以下の2つです。
- バネの中心点に向かった力を加える
- バネの中心点から離れれば離れるほど、与える力は強くなる
これらを考慮したコードは以下のようになります。
//バネによる速度の変化
vx += (springX - ball.x) * 0.07;
vy += (springY - ball.y) * 0.07;
(springX, springY)というバネの中心点の座標から、ボールの中心点の座標を引いています。 そしてそれに一定数を掛け合わせ、速度に加えています。
バネの中心点の座標と、ボールの中心点の座標の差が負の値になってもこのコードはうまく動作します。 その理由は皆さん考えてください。 上記のコードを、先ほどの摩擦の計算の前に入れましょう。このバネの力にも摩擦は考慮されるべきだからです。
そして、onEnterFrame関数の一番最後でバネの描写の関数であるdrawSpringを呼び出します。
//バネの描画
drawSpring();
ボールのドラッグ中にもバネは描画して欲しいので、onDragEnterFrame関数の最後にも入れておきましょう。
完成!!
さぁ、これでリアルな動きをするようになりました。 ボールをドラッグしてバネを伸ばし、ボタンを離してみてください。もしくは思いっきり投げつけてみましょう。
最後にここまでで出来たソースコードを掲載します。 次回のネタは今考えているところです。お楽しみに!
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Animation2 extends Sprite{
//ボール
public var ball:Sprite;
//ボールの半径
public var ballR:Number = 50;
//ボールの横方向の移動量
public var vx:Number = 0;
//ボールの縦方向の移動量
public var vy:Number = 0;
//重力によるy方向の加速度
public var ay:Number = 2;
//バネの中心点
public var springX:Number = stage.stageWidth / 2;
public var springY:Number = stage.stageHeight / 2;
//摩擦による速度の低下
public var friction:Number = 0.98;
//ドラッグ中のマウスのX,Y座標
public var tempX:Number;
public var tempY:Number;
public function Animation2(){
init();
}
public function init():void{
//ボールの作成
ball = new Sprite();
ball.graphics.beginFill(0xff0000); //赤色で塗りつぶし開始
ball.graphics.drawCircle(0, 0, ballR); //座標(0, 0)に半径50の円
ball.graphics.endFill(); //塗りつぶし終了
//ボールの位置指定(画面の真ん中)
ball.x = stage.stageWidth / 2;
ball.y = stage.stageHeight / 2;
//ボールをマウスでドラッグできるようにする
ball.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
ball.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
//ボールを画面に追加
addChild(ball);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onMouseDown(event:MouseEvent):void{
//ボールの運動を停止させる
vx = 0;
vy = 0;
//ドラッグ中はボールの移動処理をしない
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
//ドラッグ中にマウスの座標を保存する処理を登録
addEventListener(Event.ENTER_FRAME, onDragEnterFrame);
ball.startDrag();
}
private function onMouseUp(event:MouseEvent):void {
//ボールの移動処理を再開
addEventListener(Event.ENTER_FRAME, onEnterFrame);
//マウスの座標を保存する処理を除去
removeEventListener(Event.ENTER_FRAME, onDragEnterFrame);
//ボールを放り投げるX速度とY速度を設定
vx = mouseX - tempX;
vy = mouseY - tempY;
ball.stopDrag();
}
private function onDragEnterFrame(event:Event):void{
tempX = mouseX;
tempY = mouseY;
//バネの描画
drawSpring();
}
private function onEnterFrame(event:Event):void{
//速度に従ってボールの移動
ball.x += vx;
ball.y += vy;
//画面のはみ出しチェック
checkWall();
//重力による加速
vy += ay;
//バネによる速度の変化
vx += (springX - ball.x) * 0.07;
vy += (springY - ball.y) * 0.07;
//摩擦の考慮
vx *= friction;
vy *= friction;
//バネの描画
drawSpring();
}
private function checkWall():void {
//横向きのチェック
if(ball.x < ballR){
ball.x = ballR;
vx *= -0.9;
}else if(stage.stageWidth - ballR < ball.x){
ball.x = stage.stageWidth - ballR;
vx *= -0.9;
}
//縦向きのチェック
if(ball.y < ballR){
ball.y = ballR;
vy *= -0.9;
}else if(stage.stageHeight - ballR < ball.y){
ball.y = stage.stageHeight - ballR;
vy *= -0.9;
}
}
private function drawSpring():void{
//画面の中心に円の描画
graphics.clear();
graphics.beginFill(0);
graphics.drawCircle(springX, springY, 5);
graphics.endFill();
//ボールと画面の中心を線でつなぐ
graphics.lineStyle(2, 0);
graphics.moveTo(ball.x, ball.y);
graphics.lineTo(springX, springY);
}
}
}
Flex入門者がアニメーションを基礎から説明してみる #5
- 2008-08-03 (Sun)
- ActionScript , Flash/Flex
さて、今回はバネの運動を紹介しようと思いましたが、やめました。 その事前準備の説明で今回の記事は十分な長さになりそうだからです。
今回紹介するのは今までの復習のようなものです。 基本となるのははボールの落下、反射です。そこに少しだけ機能を加えてボールのドラッグと、ボールを放り投げる処理を入れて今回は終わります。 そこに次回、鮮やかな修正を加えてバネの動きを実現します。
復習 「ボールの落下、反射」
ではまず、新しいActionScriptプロジェクトを作成しましょう。 いつも通り、Flex Builder 3を前提として話していますので、他の環境の方は読み替えてください。 単にActionScriptのクラスファイルを1つ作成するだけです。 プロジェクト名、クラス名は何でもいいです。僕はAnimation2というプロジェクトを作成しました。
そこに以下のように入力しましょう。
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Animation2 extends Sprite{
//ボール
public var ball:Sprite;
//ボールの半径
public var ballR:Number = 50;
//ボールの横方向の移動量
public var vx:Number = 0;
//ボールの縦方向の移動量
public var vy:Number = 0;
//重力によるy方向の加速度
public var ay:Number = 2;
public function Animation2(){
init();
}
public function init():void{
//ボールの作成
ball = new Sprite();
ball.graphics.beginFill(0xff0000); //赤色で塗りつぶし開始
ball.graphics.drawCircle(0, 0, ballR); //座標(0, 0)に半径50の円
ball.graphics.endFill(); //塗りつぶし終了
//ボールの位置指定(画面の真ん中)
ball.x = stage.stageWidth / 2;
ball.y = stage.stageHeight / 2;
//ボールを画面に追加
addChild(ball);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void{
//速度に従ってボールの移動
ball.x += vx;
ball.y += vy;
//画面のはみ出しチェック
checkWall();
//重力による加速
vy += ay;
}
private function checkWall():void {
//横向きのチェック
if(ball.x < ballR){
ball.x = ballR;
vx *= -0.9;
}else if(stage.stageWidth - ballR < ball.x){
ball.x = stage.stageWidth - ballR;
vx *= -0.9;
}
//縦向きのチェック
if(ball.y < ballR){
ball.y = ballR;
vy *= -0.9;
}else if(stage.stageHeight - ballR < ball.y){
ball.y = stage.stageHeight - ballR;
vy *= -0.9;
}
}
}
}
最初から読み進めてきた方なら、なんなく理解できるでしょう。 今までと少し違うのはボールが枠からはみ出したかどうかのチェックをcheckWallという一つの関数に切り出したくらいです。 あと、重力の加速度を2に設定して、少し前よりも重力を強くしています。
落下はonEnterFrameの最後のvy += ay;がポイントでした。反射はcheckWall関数で枠からはみ出していたときに、速度に-0.9をかけて、反転しつつ少し絶対値を小さくしています。
Flex入門者がアニメーションを基礎から説明してみる #4
- 2008-07-28 (Mon)
- ActionScript , Flash/Flex
さて、今回は重力の働きを再現してみます。 前回はビリヤード台を上から見たようなイメージのものだったけど、それでは重力を観察できないため、横から見たイメージでいきます。 水槽の中でバウンドしているボールという感じになるでしょう。
前回の修正
前回のコードのままでは、ボールが枠の外にでてしまう可能性があります。 それを防ぐために修正を入れましょう。
onEnterFrame関数のはみ出しチェック内を以下のように修正します。
//画面領域からはみ出した場合は、移動量の正負反転
//横方向のはみ出しチェック
if(ball.x - ballR < 0){
//左方向にはみ出した
vx *= -1;
ball.x = ballR;
}else if(stage.stageWidth < ball.x + ballR){
//右方向にはみ出した
vx *= -1;
ball.x = stage.stageWidth - ballR;
}
//縦方向のはみ出しチェック
if(ball.y - ballR < 0){
//上方向にはみ出した
vy *= -1;
ball.y = ballR;
}else if(stage.stageHeight < ball.y + ballR){
//下方向にはみ出した
vy *= -1;
ball.y = stage.stageHeight - ballR;
}
はみ出したボールの位置を壁にピッタリつくところにセットしています。 座標がはみ出したままだと、何かの拍子に壁に入り込んでしまうことがあるためです。 では、今回の課題に入っていきましょう。
等加速度運動
今回の一番の肝がこれです。等加速度運動。漢字は似てるけど最初にやった等速直線運動とは別のものです。 ちなみに等速直線運動を少し思い出してみましょう。
物体が直線上をずっと同じ速度で運動する
でしたね。 地球上では摩擦があるので実際にはあまり目にすることがないのですが、ビリヤードの球とか氷の上のカーリングは摩擦が小さいので等速直線運動に近い状態です。 また、止まっている物体も速度0で等速直線運動をしていると考えられます。
つまりポイントは
周りから余計な力が働いていない
ということなのです。この条件を満たす物体は全て等速直線運動をしていると言っていいでしょう。 ちなみに自信は99%くらいなので、間違ってたら指摘しなさい。
で、等加速度運動の説明です。 等加速度運動という字を見て分かる通り
加速度がずっと等しいのです。
加速度って何か、速度に影響を与える力です。つまり何らかの力だと考えたらいいです。 そして、周りから加わる力が常に一定方向に同じ力だけ働いているのです。
例を考えてみましょう。 宇宙空間に漂うロケットを想像してください。 さっきまでエンジンを入れていたのですが、今は切っています。 するとどうなりますか? 先ほどまでの推進力の惰性で、ずっと同じスピードでスーッと動いているでしょう。
はい、これが等速直線運動。
何も力が加わってませんよね。 そして、ここでエンジンを入れました。 エンジンの出力パワーは同じまま、ゴーッとしばらくエンジンを点けたらどうなりますか? ロケットのスピードはもちろん速くなります。 どういう風に早くなるか、重い物体はスピードに乗るまでにしばらく時間がかかります。 だから初めはゆっくり、だんだん速く、グィイイイイーーーーンってスピードが上がっていくはずです。
はい、これが等加速度運動。
速度を上げるために常に同じ力で押しているので、速度はある一定のペースで増加、もしくは減少しつづけます。 プログラム的に言えば、ある一定時間ごとに速度自体を+1していると思えばいいでしょう。 そして速度は位置情報、つまり(x, y)に加算されるので、加算する値が毎回少しずつ変化するのです。 同じペースでね。
だから、等加速度運動
速度に影響を与えるものが加速度で、それが同じ大きさってこと。
重力
では、重力はどうやって表現するのか?
簡単です
等加速度運動です。 地球はその重力によって、常に地球上の物体を下に引っ張っています。 しかも、常に同じ力で(厳密には高度によって替わりますが、ほぼ一緒なので無視します)。
これって等加速度運動です。
つまり地球上にいるとき、僕たちは常に真下に向かってロケットエンジンを噴射し続けているのです。 だから、足で踏ん張って立たないといけないのですね。
Flex入門者がアニメーションを基礎から説明してみる #3
- 2008-07-22 (Tue)
- ActionScript , Flash/Flex
放置と思いきや、連続の更新ですよ。ある意味ツンデレみたいなもんですわ。 今回のテーマは「物体移動の角度と反射」です。 前回は縦方向と横方向の移動量だけを定義したけど、今回はそれに角度と速度をからめて考えます。
縦方向と横方向の移動量を決定したら角度と速度が確定します。 また、角度と速度を決定したら縦方向と横方向の移動量が確定します。 相互に変換できるので、その時々で便利な方を使うようにしましょう。
おっと、その前にタイトルを少し変えました。ActionScript→Flexに変更です。 それに合わせて過去の記事も変更させてもらいました。Flex主体で説明しているからね。
Flexにおける角度
Flexでの角度の考え方は、一般的な数学での考え方と同じです。 すなわち右に水平な方向が0度。そこから上に向かって角度が上がっていき垂直になったところが90度。 左方向に水平になって180度。下が270度で元の位置まで戻って360度です。 めんどくさいので図は用意しませんでした。
そして、一般的な数学と同じように角度から辺の長さを求めるのにsin, cos関数を使用します。 逆を求めるときは一般にatan関数を使用します。 詳しい説明はしません。 sin(角度)で実行するとその角度にふさわしいx方向の移動量が得られます。同じくcos(角度)でy方向の移動量が得られます。 これらの結果を現在の座標に加算することで、指定した角度の方向に距離1分だけ移動することになります。
Flexの事情ですが、角度をパラメータとして扱う場合、一般的な角度として扱う場合と、ラジアンという単位で扱う場合の2通りあります。 気温で言うと摂氏と華氏の違いのようなものです。 同じ角度を表すのでも違う数値になります。
そしてこれは関数毎に違うので、実行する関数によって普通の角度やラジアンを使い分けなくてはいけません。 ラジアンと角度は以下の計算で相互に変化できるので、少しめんどくさいけど問題はありません。 (Math.PIは円周率)
角度→ラジアン
(ラジアン) = (角度) x Math.PI / 180
ラジアン→角度
(角度) = (ラジアン) x 180 / Math.PI
速度
指定した角度にどれくらいの移動量で移動するか、それが速度です。 sin, cos関数で得られた(x, y)にそれぞれ速度vをかけた値を(vx, vy)とすると、現在の座標に(vx, vy)を加算したとき、 物体の移動量はvとなります。 証明はしません。そうなるのだと思ってください。 どうしても知りたい方は高校の数学か物理の範囲で検索すれば出てくるかと思います。
反射
次は反射です。 今回は壁に反射するケースだけを考えるので非常に簡単です。 左右の壁を超えた時はx方向の速度の正負を反転してあげるだけ。同じく上下の壁を超えた時はy方向の速度の正負を反転。 なぜそうなるのかは、考えましょう。
Home > Flash/Flex