dポイントプレゼントキャンペーン実施中!

ActionScriptでボールを楕円に動かすスクリプトを作成しています。
x軸、y軸に平行に動くスクリプトはできるのですが、斜め45度に動くやり方がわかりません。

↓x軸y軸に平行運動する楕円スクリプト。
//--------------------------------------------
//長軸100、短軸50の楕円形にボールを動かす
r = 100;//半径
onClipEvent (enterFrame) {
ang += 10;//角度を10ずつ追加
radian = Math.PI/180*ang;//ラジアンに変換(1度=pai割る180で計算)
X = Math.cos(radian)*r;//コサイン×半径 でx座標を計算
Y = Math.sin(radian)*r;//サイン×半径 でy座標を計算

this._x = X;//Xを座標に反映
this._y = Y/2;//Yの半分を座標に反映
}
//--------------------------------------------

なんとか傾斜した動きを作りたくていろんなサイトを見ましたが、どうしても式がわかりません。
ぜひ教えてもらえませんでしょうか。
どうぞよろしくお願いします。

A 回答 (1件)

傾斜とは、□→◇というように楕円の軌道そのものを傾けるとの意味で、よろしいでしょうか?




すご~く姑息な方法ですが。
ボールのムービークリップを別のムービークリップの入れ子にし、ボールのムービークリップを楕円の軌道で動かすスクリプトを書きます。
親のムービークリップを 45°傾けると、その子であるボールのムービークリップは傾いた座標系の中で移動しますので、結果的に傾いた楕円軌道を描いて動いているように見えます。

ただし、ボールのムービークリップにも角度が付きます。
そこで、親を傾ける角度とは逆の向き(親を 45°傾けるなら、ボールは -45°)に傾けます。
シンボルを作る時に傾けておくと簡単です。

単色の円だと分からないのですが、画像のように傾いていることがバレると困るものは、こうしてごまかしておくといいですよ。

------------------------------------------------------------------

まあ、このようなごまかしもありますけれど、もう少し真面目に考えますと。
要するに、傾斜のない状態での楕円上の位置を算出した後、この座標を 45°傾けることができればいいのだと思います。


数学で考える座標軸はX・Y・Zの3種類があります。
Flash など2Dの絵を扱うグラフィックソフトでの回転といえば、普通はZ軸を回転軸とする回転です。
ある点をZ軸回りに回転させた時、回転後の座標は

 x: X * cosθ - Y * sinθ
 y: X * sinθ + Y * cosθ
 z: Z

で、求めることができます。大文字の X Y Z が元の座標、θは回転角度です。
画面の座標は2次元なので、Zの座標は無視して構いません。

ちなみに他の軸回りに回転させた場合の式は

 X軸回り
  x: X
  y: Y * cosθ - Z * sinθ
  z: Y * sinθ + Z * cosθ

 Y軸回り
  x: Z * sinθ + X * cosθ
  y: Y
  z: Z * cosθ - X * sinθ

です。

こうして並べてみますと、2Dのグラフィックソフトは2次元座標でZ座標など考えないのに、なぜZ軸回りの回転を扱うかが分かるような気がしますね。
画面の表示に使うXとY座標をZ座標を使わずに計算できるのは、Z軸回りの回転だけだからです。

**********************

楕円軌道を傾けるには、Z軸回りの回転の式を使います。
先述の通り、この回転はZ座標を考えずにXとY座標を計算できますから、3次元座標でなくても扱えます。


次のように考えます。

まず、普通に楕円運動の計算を行い、楕円軌道上の座標を計算します。
ここで出てきた座標を使ってZ軸回りに 45°回転させる計算を行い、この計算で求められた座標を最終的なムービークリップの座標にします。

ムービークリップの座標を保持する _x と _y プロパティは、親の基準点を原点とする座標になっています。
ステージに配置したムービークリップの親は通常は _root というムービークリップであり、_root の基準点は左上です。
つまり、ステージに直接ボールのムービークリップを配置して楕円状に動かすと、ステージの左上で回ってしまうことになります。

位置は座標を求めた後で配置したい場所の座標を加算することで補正できますが、いちいちそんなことをするのは面倒です。
こちらの場合もボールのムービークリップを他のムービークリップの入れ子にしておくと、ボールの座標は親の基準点から見た座標になります。
あとはこの親をステージに配置するだけで、補正を考えることなくステージのどこにでも置くことができます。

**********************

仮に、ボールのムービークリップが他のムービークリップシンボルの中に配置されているものとします。
位置はスクリプトで決めますので、適当で構いません。

このボールを楕円状に動かし、更に楕円を 45°傾けるスクリプトは、大体、次のようになります。
このスクリプトはボールのインスタンスに設定してください。

(↓各行頭に全角のスペースが入っています。コピーする際はご注意ください)



 onClipEvent(load)
 {
  //楕円の長軸と短軸
  long_r = 100;
  short_r = 50;

  //移動速度:単位は°
  spd = 10;

  //角度を保持
  angle = 0;

  //楕円の傾斜角度と、その角度のsinおよびcos
  tilt_angle = 45;
  tilt_sin = Math.sin( tilt_angle * Math.PI / 180 );
  tilt_cos = Math.cos( tilt_angle * Math.PI / 180 );
 }


 onClipEvent(enterFrame)
 {
  //楕円上での位置を算出
  rad = angle * Math.PI / 180;
  this._x = Math.cos( rad ) * long_r;
  this._y = Math.sin( rad ) * short_r;

  //傾斜の角度だけ、座標をZ軸回りに回転させる
  this._x = this._x * tilt_cos - this._y * tilt_sin;
  this._y = this._x * tilt_sin + this._y * tilt_cos;


  //角度を更新
  angle = ( angle + spd ) % 360;
 }



Z軸回りに回転させる時にも sin と cos を使いますが、傾斜角度は常に一定なのでこの計算は1度だけで充分です。
上記のスクリプトでは load イベント発生時に計算を済ませて、結果を変数に保存しています。


楕円の傾斜角度は変数 tilt_angle に入っています。
書き換えると傾きを変更できますが、正負を問わず 90 の倍数は避けてください。

Math クラスのバグというか何と言うかなのですが、sin や cos がオーバーフロー(桁あふれが発生し、変数の値が破壊される現象)して異常な数値になる角度があります。
破壊された数値で更に計算しようとすると、動作がおかしくなるだけでなく Flash がクラッシュする場合があります。
90°単位の傾斜はこんなややこしい計算をしなくても他に方法がいろいろありますので、実際にはあまり使わないと思いますが。
    • good
    • 0
この回答へのお礼

丁寧な解説と実際のスクリプトまで書いていただいてありがとうございます。
大変分かりやすく、また知らないこともいっぱいあったのでとても勉強になりました。

いただいた解説と「教えてgoo」の数学の方にあった記事で、自分なりにスクリプトを組んでみました。
自分の備忘もかねて掲載いたします。
参考
・教えてgoo「これはなぜ楕円なんですか?」ページ
 http://oshiete1.goo.ne.jp/kotaeru.php3?q=1519820
・「回転移動の1次変換」サイト
 http://www.geisya.or.jp/~mwm48961/kou2/linear_im …

//-----以下スクリプト
onClipEvent (load) {
center = Stage.width/2; //楕円の中心座標
r_long =100; //長軸
r_short = 50; //短軸
degree = 45; //傾斜度
slope = Math.PI/180*(degree); //楕円の傾斜角度をラジアンに変換
sin_slope = Math.sin(slope); //傾斜用のサイン
cos_slope = Math.cos(slope); //傾斜用のコサイン
}

onClipEvent (enterFrame) {
/*
原点中心に角θだけ回転させる変換式
 傾斜用x'=xcosθ-ysinθ  傾斜用y'=xsinθ+ycosθ
▼θ=45度にする場合
 傾斜用新x = x(※cos(radian)×長軸)×cos(45度) - y(※sin(radian)×短軸)×sin(45度)
 傾斜用新y = x(※cos(radian)×長軸)×sin(45度) + y(※sin(radian)×短軸)×cos(45度)
*/

ang += 10; //移動速度(角度)を追加
radian = Math.PI/180*ang; //角度angをラジアンに変換(360度=2PI、180度=PI、90度=PI/2、1度=PI/180)

x1 = Math.cos(radian)*r_long; //傾斜前のx座標→コサイン × 長軸
y1 = Math.sin(radian)*r_short; //傾斜前のy座標→サイン × 短軸

//傾斜用新x = 現在のxの長さ×cos(45度)- 現在のyの長さ×sin(45度)
newx = (x1*cos_slope) - (y1*sin_slope);
//傾斜用新y = 現在のxの長さ×sin(45度)+ 現在のyの長さ×cos(45度)
newy = (x1*sin_slope) + (y1*cos_slope);

this._x = newx + center;
this._y = newy + center;
}
//-----スクリプト終わり

お礼日時:2007/04/20 20:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!