今回は,3次元空間でインスタンスを回してみたい。インスタンスを3次元空間で操作するやり方はいくつかある。手軽なものから順に試していこう。
インスタンスを3次元空間のプロパティで操作する
2次元平面でインスタンスを回そうとするとき,手っとり早いのはDisplayObject.rotationプロパティを使うことだ。3次元空間の操作についても,これに相当するプロパティがある。DisplayObject.rotationX/DisplayObject.rotationY/DisplayObject.rotationZプロパティだ。それぞれxyzの各軸回りの角度を度数値で示す。2次元と3次元の違いはあるものの,プロパティの扱い方は変わらない。実際,DisplayObject.rotationプロパティは,3次元で考えればz軸を中心にした回転なので,DisplayObject.rotationZプロパティと同じ値だ。
それでは,DisplayObject.rotationYプロパティを使って,タイムラインに置いたインスタンスmy_mcを,マウスポインタの水平位置に応じてy軸で回転させてみよう。以下のフレームアクションは,マウスポインタとインスタンスとの水平座標の差に応じて回転角を計算し,その値をDisplayObject.rotationYプロパティに設定することにより,インスタンスを水平に回転させる(図1)。なお,インスタンスの基準点は中心にしてある。
// タイムライン: メイン
// タイムラインにMovieClipインスタンスmy_mcを配置
var nX:Number = my_mc.x;
var nDeceleration:Number = 0.3;
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
my_mc.rotationY += (mouseX - nX) * nDeceleration;
trace(my_mc.rotationY); // 確認用
}
とても簡単だ。だが,ひとつ気になることがある。確認用に加えたtrace()関数は,回転したインスタンスのDisplayObject.rotationYプロパティの度数値を[出力]する。放っておくと,その数値の桁数はどこまででも増えていく(図2)。
[ヘルプ]のDisplayObject.rotationYプロパティの項を見ると,値は±180の範囲に調整されるように説明されている。確かに,2次元平面のDisplayObject.rotationプロパティは,そのように角度が換算される。ところが,3次元空間のプロパティDisplayObject.rotationX/DisplayObject.rotationY/DisplayObject.rotationZについては,実際には何の調整もされない。
もちろん,どれだけ桁数が増えてもプロパティが正しくその値を扱えるなら構わない。しかし,内部的に扱える値の範囲は決まっているはずであり,それを超えれば意図しない結果が生じ得る。仕方がないので,自力でその範囲を定めるようにしよう。
角度の値を±180の範囲に定める
角度の値は[ヘルプ]に書かれていた±180に納めることにしよう。実は,角度を0から360までの値に換算する方法はすでに学んだ(第16回「三角関数を使った楕円軌道のアニメーション」「円や楕円軌道のアニメーション」)。角度が変数nDegreeに納められていたとすると,つぎの式で0以上360未満の値に換えられた。
nDegree = (nDegree % 360 + 360)% 360
では,値の範囲を±180にするにはどうするか(※1)。あらかじめ角度に180を足したうえで,上の式により0から360までの値に換算し,その後180差引けばよい。値を±180の範囲に換算する演算は,別に関数として定めよう。その関数xGetDegrees()を加えたのが,つぎのスクリプト1だ。
スクリプト1 インスタンスの基準点からのマウスポインタの水平位置に応じてインスタンスを水平回転
// タイムライン: メイン
// タイムラインにMovieClipインスタンスmy_mcを配置
var nX:Number = my_mc.x;
var nDeceleration:Number = 0.3;
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
var nRotationY:Number = my_mc.rotationY + (mouseX - nX) * nDeceleration;
my_mc.rotationY = xGetDegrees(nRotationY);
// trace(my_mc.rotationY); // 確認用
}
function xGetDegrees(nDegrees:Number):Number {
nDegrees += 180;
nDegrees %= 360;
nDegrees += 360;
nDegrees %= 360;
nDegrees -= 180;
return nDegrees;
}
動きは前掲のフレームアクションと変わりはない。ただ,コメントアウトしてある確認用のtrace()関数のステートメントを有効にしてみれば,DisplayObject.rotationYプロパティの値が±180の範囲に収まっていることが確かめられる(図3)。なお,関数xGetDegrees()の中のステートメント行数が,やけに多いように感じるかもしれない。ただ,これは値を0から360までの範囲に換算する前掲式も,細かくステートメントに分けたに過ぎない。
- ※1
- DisplayObject.rotationYプロパティに設定する数値の範囲は,0から360まででもとくに問題は生じないだろう。ただ,念のため[ヘルプ]の記述に値の範囲を合わせ,また±180にする場合の計算を練習してみた。


