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

第34回 3次元空間における回転

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

今回は,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);   // 確認用
}

図1 インスタンスの基準点から見たマウスポインタの水平位置に応じてインスタンスが水平回転

図1 インスタンスの基準点から見たマウスポインタの水平位置に応じてインスタンスが水平回転

とても簡単だ。だが,ひとつ気になることがある。確認用に加えたtrace()関数は,回転したインスタンスのDisplayObject.rotationYプロパティの度数値を[出力]する。放っておくと,その数値の桁数はどこまででも増えていく図2)。

図2 DisplayObject.rotationYプロパティの値の範囲に制限がない

図2 DisplayObject.rotationYプロパティの値の範囲に制限がない

[ヘルプ]の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までの範囲に換算する前掲式も,細かくステートメントに分けたに過ぎない。

図3 DisplayObject.rotationYプロパティの値が±180の範囲に収まっている

図3 DisplayObject.rotationYプロパティの値が±180の範囲に収まっている

図3 DisplayObject.rotationYプロパティの値が±180の範囲に収まっている

※1
DisplayObject.rotationYプロパティに設定する数値の範囲は,0から360まででもとくに問題は生じないだろう。ただ,念のため[ヘルプ]の記述に値の範囲を合わせ,また±180にする場合の計算を練習してみた。

著者プロフィール

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

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

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入