ActionScript 3.0で始めるオブジェクト指向スクリプティング

第36回 Matrix3Dクラスの後から加える変換

この記事を読むのに必要な時間:およそ 3 分

動的に配置したビットマップをマウスポインタに応じて上下左右に回す

それでは改めて前回の課題だった,動的に配置したビットマップを,マウスポインタの動きに応じて上下左右に回してみよう。前回マウスポインタの動きとインスタンスの回る方向がちぐはぐだったのは,Matrix3D.prependRotation()メソッドを使ったからだ。

たとえば,インスタンスがy軸で横に回転していたとき図3上図⁠,マウスポインタを上に動かせば,インスタンスは横向きのまま垂直に回ることを期待する。ところが,Matrix3D.prependRotation()メソッドを用いると,インスタンスはデフォルトの正面向きで上に回転して,その後直前の状態の変換を加えることになってしまう図3下図⁠。

図3 Matrix3D.prependRotation()メソッドは正面向きのインスタンスを回すことになる

直前の状態

画像

デフォルト状態

画像

Matrix3D.prependRotation()メソッドを適用

画像

直前の変換を適用

画像

直前の状態に対して変換を加えたいなら,後から適用するappendのメソッドを用いる必要がある。平行移動や回転あるいは伸縮の変換を後から加えるには,prependのメソッドに対応するMatrix3D.appendTranslation()Matrix3D.appendRotation()Matrix3D.appendScale()といったメソッドをそれぞれ用いる。これらのメソッドは変換を後から加えるという違いがあるだけで,引数は変わらない。

Matrix3Dオブジェクト.appendTranslation(移動x座標値, 移動y座標値, 移動z座標値)
Matrix3Dオブジェクト.appendRotation(回転度数値, 回転軸)
Matrix3Dオブジェクト.appendScale(水平伸縮率, 垂直伸縮率, 奥行き伸縮率)

もっとも,Matrix3D.prependRotation()メソッドをMatrix3D.appendRotation()に変えただけでは,インスタンスを上下左右に回すことは思惑どおりにいかない。MovieClipインスタンスmy_mcをステージ中央に置いて,Matrix3D.appendRotation()メソッドによりy軸で単純に水平に回してみよう。フレームアクションはつぎのとおりだ。

// タイムライン: メイン
// タイムラインにMovieClipインスタンスmy_mcを配置
my_mc.z = 0;
var myMatrix3D:Matrix3D = my_mc.transform.matrix3D;
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
  myMatrix3D.appendRotation(5, Vector3D.Y_AXIS);
}

[ムービープレビュー]を確かめると,確かにインスタンスは水平に回る。ただし,回転の軸がインスタンスの基準点ではない。実は,行列による座標変換は,原点がつねにインスタンスの置かれた親タイムラインの基準点になる。メインタイムラインなら,水平回転のy軸はステージ左端だ図4⁠。そして,この原点は動かせない。

図4 メインタイムラインは水平回転のy軸はステージ左端になる

図4 メインタイムラインは水平回転のy軸はステージ左端になる

Matrix3D.prependRotation()メソッドではインスタンスの基準点を軸に回ったのは,デフォルト状態つまり座標(0, 0)ではインスタンスと親タイムラインの基準点が一致するためだ。後から変換を加えるMatrix3D.appendRotation()メソッドでは,インスタンスと親タイムラインの基準点の位置は通常異なる。

とはいえ,対処法はさほど難しくない。インスタンスの角度は変えずに,回転の軸だけずらせばよい。つまり,インスタンスの座標のみ親タイムラインの基準点に移動すれば,直前の角度からインスタンスの基準点で回転できる。その後忘れずに,座標はもとの位置に戻す。つまり,平行移動・回転・平行移動を組合わせるということだ。

前回つくった動的に配置したビットマップをマウスポインタに応じて水平回転させるのスクリプト1に,垂直の処理を加えたのが以下のスクリプト1だ。垂直方向の回転角を計算したうえで,インスタンスは親タイムラインの基準点に移動してから回転し,改めてもとの位置に戻した。

スクリプト1 インスタンスの基準点からのマウスポインタの位置に応じてインスタンスを水平・垂直回転

// タイムライン: メイン
// [ライブラリ]のビットマップに[クラス]としてImage0を設定
var mySprite:Sprite = new Sprite();
var myBitmap:Bitmap = new Bitmap(new Image0(0, 0));
var nX:Number = stage.stageWidth / 2;
var nY:Number = stage.stageHeight / 2;
var nDeceleration:Number = 0.3;
mySprite.z = 0;
var myMatrix3D:Matrix3D = mySprite.transform.matrix3D;
mySprite.x = nX;
mySprite.y = nY;
myBitmap.x = -myBitmap.width / 2;
myBitmap.y = -myBitmap.height / 2;
addChild(mySprite);
mySprite.addChild(myBitmap);
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
  var nRotationY:Number = (mouseX - nX) * nDeceleration;
  var nRotationX:Number = (mouseY - nY) * nDeceleration;
  myMatrix3D.appendTranslation(-nX, -nY, 0);   // 親タイムラインの基準点に移動
  myMatrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);   // 水平回転
  myMatrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);   // 垂直回転
  myMatrix3D.appendTranslation(nX, nY, 0);   // もとの位置に戻る
}

[ムービープレビュー]を確かめると,今度は直前の状態からインスタンスの中心を軸にマウスポインタの向きに回る図5⁠。2回にわたって見てきたように,単純な変換であれば前に加えるメソッドの方が簡単に書ける。しかし,いくつかの変換を組合わせてアニメーションするような場合には,後から加えるメソッドの方がステートメント数は増えるものの,細かく処理できる。

図5 マウスポインタの動きとインスタンスの回転する方向が一致する

図5 マウスポインタの動きとインスタンスの回転する方向が一致する

次回は,回す面の数を増やし,その重ね順について解説したい。

今回解説した次のサンプルファイルがダウンロードできます。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書