こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

正6面体を一定の角度で回転させたい

私は今、FlashMX Professional 2004 ver7.2を使っている者なのですが、ワイヤーフレームでできた正6面体(キューブ)を一定の角度で回転させるアニメーションがActionScriptで作りたいと思っています。

それで、Flash製作に関するHPを色々探して見たのですが、私の調べた限りでは、どのHPも、マウスカーソルに反応して回転の角度が変わるアニメーションのスクリプトしか公開されておりませんでした。

私としては、マウスに反応しないアニメーションを作りたいのですが、いかんせんActionScript初心者なので、上記で見つかったアニメーションのどのスクリプトを修正すればいいか、分からないでいます。

マウスの動きに反応せずに正6面体を回転させるアニメーションの作成方法をご存知の方がいらっしゃいましたら、よろしければそのスクリプトを、もしご面倒なようでしたら、参考になるHPをお教えくだされば幸いに思います。



また、こちらは余裕があればお答え頂くと言う形でよいのですが、こうしたアニメーションを表現するもう一つの手段として、ActionScriptを使わずに、思い切ってフレームアニメーションで回転しているように見せる、と言う方法もあるのですが、こちらの方法では動作が遅くなるほどサイズが重くなってしまうでしょうか?

よろしければアドバイス頂けると幸いに思います。

投稿日時 - 2005-06-13 10:28:47

QNo.1446117

暇なときに回答ください

質問者が選んだベストアンサー

Flash で配信されている3DCGらしきものは、殆どが、3DCGソフトでモデルを作って、様々な角度から撮影(レンダリング)したものを静止画で書き出し、Flash に読み込んで各フレームに配置したフレームアニメです。
この方法では Flash だけではできないきれいな3DCGも作れますが、当然ながら、コマ数が多くなるほどムービーは重くなります。
複雑な動きをするものやなめらかなアニメほど、読み込みには時間がかかっています。

解説サイトで紹介されているアクションは、おそらく、マウスの動きから回転する角度を算出し、対応する角度の絵が配置されているフレームを計算するものではないでしょうか。
フレームアニメにして再生したいだけなら、複雑なスクリプトは必要ありません。


ちなみに、3DCGソフトの中には、3Dモデルの輪郭線をなぞって Flash と同じく2Dの線や塗りでデータを作り、最初から Flash ムービーとして書き出す、”トゥーンレンダリング”という機能があるものも存在します。

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

JPEG などのビットマップ系画像は、方眼紙のマス目に色を付けたような形で絵の情報を記録しています。
計算によりマス目の大きさを変えたり、削除して縮めることは可能ですが、絵の情報が破損して絵が汚くなってしまいます。
一方3DCGは、3次元の座標を持つポリゴンという多角形(大抵は三角形か四角形)を組み合わせてモデルを作り、これをある視点から見た見え方を計算して描画します。
ある座標系にある点を移動・回転・拡大/縮小した時にどの座標に移動するかは、数学的に計算できます。
絵の情報を細かい座標値にして持つことで、計算によってきれいな線を描画したり、立体感のある映像を描画できる仕組みにしたところが、3DCGの画期的な点なのです。

広告や映画・ゲーム等で広く使われている3DCGは、視点・複雑な親子階層・光源・ポリゴンに色や模様を付ける処理などがあり、これを全部 Flash でやろうとすると難しくなってしまいます。
しかし、簡単な立体をワイヤフレームで表示するくらいなら、Flash でも何とかなります。
ちょっと難しいですけれど、計算で描くワイヤフレームアニメの作り方をご紹介します。

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

こんなふうに考えます。

絵のない空っぽのムービークリップを作り、この中にワイヤフレームの描画に必要な関数やデータを定義します。
立方体の頂点データは配列変数で持ちます。
立方体の頂点は8つですが、6つの正方形でできているので、面は6つ、頂点は4x6= 24 で 24 点とも考えられます。
(8点で計算する高速な方法もありますが、今回は速度よりも、ポリゴンの考え方が分かりやすい方法をとりたいと思います)
これらの頂点を回転した時にどの座標になるかを計算し、それを別の配列に格納しておきます。
ムービークリップの機能として、直線を描画できるスクリプトが利用できます。
移動した頂点が求められれば、あとは直線で頂点をつないで出来上がりです。
角度を連続的に更新すれば自動でクルクル回るようになりますし、ムービークリップなので移動したり拡大・縮小して、ズームのような演出をすることも可能です。


回転後の頂点の計算式は、どの軸回りに回転させるかによって異なります。
X , Y , Z はもとの頂点の各座標値、Aは回転角度を表します。

 X軸回り
  x: X
  y: Y * cos( A ) - Z * sin( A )
  z: Y * sin( A ) + Z * cos( A )

 Y軸回り
  x: Z * sin( A ) + X * cos( A )
  y: Y
  z: Z * cos( A ) - X * sin( A )

 Z軸回り
  x: X * cos( A ) - Y * sin( A )
  y: X * sin( A ) + Y * cos( A )
  z: Z

モニターの座標は2次元なので、線を引く時は z の座標は無視して構いません。
このあたりで拒絶反応が出そうですが(^^;)、もうちょっと頑張ってくださいね。

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

実際に作ってみましょう。

「挿入」→「新規シンボル」で、ムービークリップシンボルを1つ作ります。
絵は描かないで、タイムラインのフレーム1にキーフレームを作り、次のようなスクリプトを書きます。

(↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください。このまま使うとシンタックスエラーになります)


 //正6面体のポリゴンデータ:
 //ムービークリップの中心点を中央とする100x100x100の立方体
 poly = new Array();
 //上面
 poly[ 0 ] =
 [
  { x : -50 , y : -50 , z : -50 } , { x : 50 , y : -50 , z : -50 },
  { x : 50 , y : -50 , z : 50 } , { x : -50 , y : -50 , z : 50 }
 ];
 //左側面
 poly[ 1 ] =
 [
  { x : -50 , y : -50 , z : -50 } , { x : -50 , y : -50 , z : 50 },
  { x : -50 , y : 50 , z : 50 } , { x : -50 , y : 50 , z : -50 }
 ];
 //右側面
 poly[ 2 ] =
 [
  { x : 50 , y : -50 , z : 50 } , { x : 50 , y : -50 , z : -50 },
  { x : 50 , y : 50 , z : -50 } , { x : 50 , y : 50 , z : 50 }
 ];
 //前面
 poly[ 3 ] =
 [
  { x : -50 , y : 50 , z : 50 } , { x : 50 , y : 50 , z : 50 } ,
  { x : 50 , y : -50 , z : 50 } , { x : -50 , y : -50 , z : 50 }
 ];
 //背面
 poly[ 4 ] =
 [
  { x : -50 , y : -50 , z : -50 } , { x : 50 , y : -50 , z : -50 },
  { x : 50 , y : 50 , z : -50 } , { x : -50 , y : 50 , z : -50 }
 ];
 //底面
 poly[ 5 ] =
 [
  { x : -50 , y : 50 , z : -50 } , { x : 50 , y : 50 , z : -50 },
  { x : 50 , y : 50 , z : 50 } , { x : -50 , y : 50 , z : 50 }
 ];


 //移動後の頂点を格納する配列
 //初期値はダミー
 vertex = new Array();
 for( var i = 0 ; i < 6 ; i++ )
 {
  vertex[ i ] =
  [
   { x : 0 , y : 0 , z : 0 } , { x : 0 , y : 0 , z : 0 },
   { x : 0 , y : 0 , z : 0 } , { x : 0 , y : 0 , z : 0 }
  ];
 }


 ///////////////////////////////////////////////////////////////////////////////
 //頂点を指定の軸回りに回転する関数
 //引 数  ver    :もとの頂点データを格納する変数
 //     shift_ver :移動後の頂点データを格納する変数
 //     angle   :回転角度(単位は°)
 //     axis   :回転軸を表す文字( X : X軸 Y : Y軸 Z : Z軸) 
 ///////////////////////////////////////////////////////////////////////////////

 function Rotation( ver:Object , shift_ver:Object , angle:Number , axis:String )
 {
  var rad , sin , cos;

  //回転角度をラジアンに変換して三角関数を求める
  rad = angle * Math.PI / 180;
  sin = Math.sin( rad );
  cos = Math.cos( rad );


  //指定の回転を中心とした、回転後の座標値を求める
  switch( axis )
  {
   //X軸回りの回転
   case 'X':
    shift_ver.x = ver.x;
    shift_ver.y = ver.y * cos - ver.z * sin;
    shift_ver.z = ver.y * sin + ver.z * cos;
    break;

   //Y軸回りの回転
   case 'Y':
    shift_ver.x = ver.z * sin + ver.x * cos;
    shift_ver.y = ver.y;
    shift_ver.z = ver.z * cos - ver.x * sin;
    break;

   //Z軸回りの回転
   case 'Z':
    shift_ver.x = ver.x * cos - ver.y * sin;
    shift_ver.y = ver.x * sin + ver.y * cos;
    shift_ver.z = ver.z;
    break;

   default:
    break;
  }
 }


 ///////////////////////////////////////////////////////////////////////////////
 //ポリゴンの描画関数
 ///////////////////////////////////////////////////////////////////////////////

 function Draw_Polygon()
 {
  var i , j;

  //今まで引かれていた線を全て消去
  this.clear();

  //線のスタイルを設定
  this.lineStyle( 1 , 0x000000 , 100 );

  //ポリゴンの描画
  for( i = 0 ; i < 6 ; i++ )
  {
   //描画開始位置に移動
   this.moveTo( vertex[ i ][ 0 ].x , vertex[ i ][ 0 ].y );

   //四角形の左上の頂点から右回りに線を引く
   for( j = 1 ; j <= 3 ; j++ )
   {
    this.lineTo( vertex[ i ][ j ].x , vertex[ i ][ j ].y );
   }

   //3つめの頂点から最初の頂点までの線を引く
   this.lineTo( vertex[ i ][ 0 ].x , vertex[ i ][ 0 ].y );
  }
 }


 ///////////////////////////////////////////////////////////////////////////////
 //ワイヤフレームの立方体を回転させて描画する関数
 //引数 各軸ごとの回転角度
 //   rot_x:X軸回り rot_y:Y軸回り rot_z:Z軸回り 
 ///////////////////////////////////////////////////////////////////////////////

 function WireFrame( rot_x:Number , rot_y:Number , rot_z:Number )
 {
  var ver , shift1 ,shift2 , shift3 , i , j;

  //関数にデータを渡すためのオブジェクトを生成
  ver = new Object();
  shift1 = new Object();
  shift2 = new Object();
  shift3 = new Object();


  //各頂点を指定の軸回りに回転させた後の座標を求める
  for( i = 0 ; i < 6 ; i++ )
  {
   for( j = 0 ; j < 4 ; j++ )
   {
    //回転する頂点をセット
    ver.x = poly[ i ][ j ].x;
    ver.y = poly[ i ][ j ].y;
    ver.z = poly[ i ][ j ].z;

    //X→Y→Z軸回りの順に回転
    Rotation( ver , shift1 , rot_x , "X" );
    Rotation( shift1 , shift2 , rot_y , "Y" );
    Rotation( shift2 , shift3 , rot_z , "Z" );

    //移動後の頂点をセット
    vertex[ i ][ j ] = { x : shift3.x , y : shift3.y , z : shift3.z };
   }
  }

  //ポリゴンを描画
  Draw_Polygon();
 }


 //とりあえず、静止状態を描画
 WireFrame( 0 , 0 , 0 );

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

紙面の都合上、1つ1つを詳しくは説明できませんが。


立方体の頂点データは、poly という配列変数に入っています。
立方体は、ムービークリップの中心点( 0 , 0 , 0 )の地点を中央とする、100 x 100 x 100 の立方体を想定しています。
中心点が0ですから、各軸とも -50 ~ 50 の範囲を占有する立方体となります。図を描いて考えてみてください。
なお、Z軸は画面手前が正、奥が負になっています。
この配列変数は6x4の2次元配列です。各変数の1つ1つが、x , y , z というラベルのようなものが付いた要素を持っていて、3次元の座標を管理しています。

vertex も配列変数で、構造は poly と同じく6x4、x , y , z のラベルを持っています。
最初に初期値を入れておかないと上手く動かないので、仮に全て0を入れています。
この配列変数には、poly の座標を回転した後の座標が入り、線を引く時に利用されます。


Rotation 関数が、今回のヤマ場です。
今の座標値と回転角度を指定して呼び出すと、回転後の座標を計算して返します。
ただし、もとの座標も計算後の座標も3つずつありますので、これを1つ1つ引数として渡していたのでは大変です。
そこで、Object 型という汎用の変数を作り、この中にまとめて入れてやりとりできるようにしています。
最初の引数がもとの座標を渡すため、次の引数が計算後の座標を受け取るための Object 型の変数です。
(呼び出し方はスクリプトを参考にしてください)
なお、どの軸回りに計算するかは、文字で指定するようにしています。

Draw_Polygon 関数は、各頂点を直線でつないでワイヤフレームで描画する関数です。
移動後の頂点は配列変数 vertex に入っているので、その内容を見ながら線を引いています。
ムービークリップに絵がないのにワイヤフレームの絵が表示されるとは不思議ですが、それはこの関数の働きのおかげです。

WireFrame 関数は、角度を指定するだけで回転をかけられるようにしています。
引数は左から順に、X・Y・Z軸回りの、各回転角度です。
sin や cos はラジアンという厄介な単位が必要ですが、Rotation 関数の中で角度をラジアンに変換していますから、回転させたい角度は度(°)で指定してください。


このムービークリップをステージに配置すると、最初は何の変哲もない、ただの四角形が表示されます。
これは、立方体の側面を真正面から見ている状態です。
ムービークリップに設定したスクリプトには、アニメーションの処理がありません。具体的に立方体を回転させる部分は、別に作る必要があります。
この処理を別にすることで、いろいろな回転アニメや拡大/縮小などに利用できるようにしています。

真正面から見ている状態ですから、各軸とも単体で回転させると今ひとつ立体感がなく、面白くも何ともないアニメになります。
例えば、このムービークリップのインスタンスをステージに置いて


 onClipEvent(load)
 {
  //回転させる角度を保持
  angle = 0;

  //アニメーションの間隔のカウンタ
  wait = 0;
 }

 onClipEvent(enterFrame)
 {
  //5フレームに1度、Y軸回りに5°ずつ回転
  wait++;

  if( wait >= 5 )
  {
   //角度を更新:360°を超えないようにする
   angle += 5;
   if( angle >= 360 )
   {
    angle = 0;
   }

   //Y軸回りに回転
   WireFrame( 20 , angle , 50 );

   //間隔のカウンタをリセット
   wait = 0;
  }
 }


こんな感じのスクリプトを設定すると、3DCGらしい雰囲気になります。
上記のスクリプトですと、X軸回りに 20°、Z軸回りに 50°、Y軸回りの回転は5フレームごとに角度が 5°ずつ更新され、くるくる回って見えます。
(遠近感がついていないので、ずっと見ていると錯覚することがありますが、画面左上方向を向き、右回りに回っています)
WireFrame 関数に渡す数値をいろいろ変更して、面白い角度を探してみてください。

このムービークリップは最初のフレームに絵がないため、ステージでは○印に+の印が重なったマークとして表示されますが、これは正常です。
スクリプトは通常のムービークリップと同様に設定できます。

なお、最初は全く回転していない状態の立方体が描画されてしまいます。
ムービークリップのシンボルを開き、タイムラインに設定したスクリプトの最後の部分、

 //とりあえず、静止状態を描画
 WireFrame( 0 , 0 , 0 );

このスクリプトを削除してください。


インスタンスに名前を付けて、他のインスタンスから操作することもできます。
ボタン操作で自由に回転するといったことにも利用できます。
どの場合も、WireFrame 関数に回転角度を指定して呼び出すだけで立方体を回転できるようになっています。
ただし、この関数はこのムービークリップの持ち物になっていますので、他のムービークリップやボタンから呼び出す時は、階層の指定(ターゲットパス)にご注意ください。


3DCGは難しいですね。世に出回っている3DCGが、すごく偉大に見えます ^^;
長々とすみませんでした。
不明な点がありましたら、補足してください。

投稿日時 - 2005-06-15 00:56:30

補足

質問者です。
先ほどは御回答ありがとうございました。

さて、早速ですが不可解な現象が起こってしまいました^^;

回答で御説明くださったスクリプト、
「//正6面体のポリゴンデータ: ~ //ポリゴンを描画Draw_Polygon();} 」
をレイヤー1:フレーム1に、
「onClipEvent(load) ~ //間隔のカウンタをリセット wait = 0; } }」
をシンボル1(ムービークリップ)に書き込んでみたのですが、
ムービープレビューしたところ、何も表示されないという現象が起こってしまいました。
それも、「//とりあえず、静止状態を描画 WireFrame( 0 , 0 , 0 );」を削除する前はきちんと正四角形が表示されたにもかかわらずです。

さらに、レイヤー1:フレーム1の自動フォーマットを試してみたところ、「シンタックスエラーがある」ということだったので、シンタックスチェックをやってみたのですが「エラーはありません」と表示されてしまい、2つの点で途方に暮れています。

もしかすると、何も表示されない原因はここにあるのではないか、と勝手に推測しているのですが、実際どこで間違えてしまったのでしょうか?
スクリプトを書く場所を間違えてしまったのでしょうか?

投稿日時 - 2005-06-15 11:26:01

お礼

詳細な御説明ありがとうございます。

ただ単に3DをFlashで表現するといっても、作る物によって難易度は全然違ってくるのですね。
御紹介頂いたスクリプトなら、私でも少し応用ができそうです^^

やはり、回転にはZ軸という考え方を使っていいのですね。
私が見たFlash作成HPの中には、回転に関して、X軸とY軸だけしか用いていないところがあり、少し違和感があったのですが…。


さっそく、この方法でも試してみたいと思います。
ありがとうございました。

図々しいかも知れませんが、また不明な部分がありましたら、この場でそれをお伝えいたします。

ありがとうございました。

投稿日時 - 2005-06-15 10:57:17

ANo.2

このQ&Aは役に立ちましたか?

5人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

DPE

#2です。


「 //正6面体のポリゴンデータ・・・」から 「 WireFrame( 0 , 0 , 0 ); 」までのスクリプト(ポリゴンの頂点の定義から計算・描画用の関数と、サンプルとして真正面から見た立方体を表示する処理まで)を、メインのタイムラインのフレーム1に書いていませんでしょうか?
このスクリプトは、新規に作った空のムービークリップが持っているタイムラインの、フレーム1に設定します。
最初に四角形が表示された時、この四角形はどこに表示されましたでしょうか。
ステージの左上の方に表示されたのなら、これらのスクリプトをメインのタイムラインに書いたことが原因と思われます。

タイムラインの上の方を見てください。
ここに「シーン 1 」としか表示されていないのであれば、編集中のタイムラインはメイン(ムービーそのもの)のタイムラインです。
シンボルを編集している時は、「シーン 1 」「(編集中のシンボルの名前)」と表示されます。
ムービークリップのシンボルの編集画面は特に、ムービーそのものの編集画面とレイアウトが全く同じで紛らわしいです。どのタイムラインを編集しているか分からなくなったら、この表示を見て確認してください。
スクリプトを設定したタイムラインが違っているようでしたら、「シンボル1」の編集画面を開いて、スクリプトを移動してみてください。


ActionScript では、参照したいインスタンスや変数・関数を持っている階層がどこなのかを、はっきりと指定して操作しなければなりません。この指定のことを、ターゲットパスといいます。
メインのタイムラインに座標の計算や描画関数の定義等を書いた場合、WireFrame 関数は _root という階層の持ち物になります。
メインのタイムラインで WireFrame 関数が定義されていたとすると、この関数は「シンボル1」のインスタンスのものではないので、

 _root.WireFrame( ・・・ );

または

 _parent.WireFrame( ・・・ );

このように、ターゲットパスを付けた書き方でないと呼び出せません。
最初の WireFrame( 0 , 0 , 0 ); は、関数の持ち主と同じタイムラインで呼び出しています。
ActionScript では、自分が持っている関数や変数・インスタンスを利用するなら、ターゲットパスを省略できる決まりになっています。
関数がメインのタイムラインで定義されていたとしても、WireFrame( 0 , 0 , 0 ); は同じタイムライン上で呼び出しているので最初の四角形は表示されます。
ところが、このスクリプトを消してムービークリップから呼び出すようにすると、ターゲットパスがないために関数が呼び出しに失敗して、何も表示されなくなるというわけです。

#2のスクリプトでは、ムービークリップシンボルのタイムラインで各関数を定義しています。
onClipEvent を設定したムービークリップ(のインスタンス)はこのシンボルの分身ですから、シンボルと同じ関数を内部に持っています。
WireFrame 関数は自分のものですので、ターゲットパスを付けなくても呼び出せます。

他のムービークリップから呼び出したい時は、立方体を描画するインスタンスまでのターゲットパスが必要です。
例えば、このインスタンスに” cube ”とインスタンス名を付けたとすると、

 _root.cube.WireFrame( 0 , 0 , 0 );

このようなターゲットパスを付けて呼び出します。
ターゲットパスを自動で入力してくれる機能があります。
「アクション」パネルの上部に7つほどアイコンが並んでいますが、この中の中央のアイコンをクリックしてください。リストから対象を選ぶだけで、そこまでのターゲットパスが自動で入力されます。
ターゲットパスがよく分からない時に利用してみてください。


3Dの計算と描画関数をムービークリップシンボルのタイムラインで定義すると、立方体はムービークリップ自身の座標系を中心に描画されます。
つまり、ステージではムービークリップを置いた地点を中心にして立方体が描画されますので、どこでも好きな位置に立方体を配置できます。
しかし、メインのタイムラインにスクリプトを書いた時は、ステージの中心点(左上)を基点に立方体が描画されてしまい、融通が利かなくなります。

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

スクリプトの書き方やレイアウトは人によって様々です。
私は { } で1行ずつ使って段落のようにする書き方が気に入っていますが、自動フォーマットでは、これがシンタックスエラーとして扱われることがあります。
しかし、この書き方は文法上は間違いではないので、シンタックスチェックをすると誤りはないと出てきます。
本当にシンタックスエラーがある時は、「ムービープレビュー」や「パブリッシュ」の際にエラーが報告されます。
何の報告もないのに上手く動かないようなら、エラーではなく、バグ(文法に間違いはないが、スクリプトの組み方に不具合がある)があるということです。

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

ところで、アニメのサンプルスクリプトですが。
5フレームに1度だと、動きがちょっとカクカクしてしまいますね。
onClipEvent(enterFrame) の中の

 if( wait >= 5 )



 if( wait >= 3 )

くらいにしてみてください。3フレームに1度、回転の計算が行われます。
それから回転する角度ですが、これはいろいろ変えてみて、面白い角度やお好みの角度を見つけていただきたいのですが、

 //X軸回りに回転
 WireFrame( angle , -20 , 50 );

こんな角度もちょっと面白かったので、よろしければお試しください。
(白状しますと、#2の角度は適当に作った試験用のデータでした ^^ゞ)
変数を2つ作って

 //X・Y軸を同時に回転
 WireFrame( angle_x , angle_y , 50 );

このように2つの軸回りに同時に動かしても、面白い回り方になります。
同様にして3軸回りに同時に回転させることもできますけれど、やりすぎると妙な動きになって3D酔いしてしまうので、ほどほどにしましょう。

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

今回は立方体だったのですが、配列変数 poly に入れたポリゴンの頂点データを変えると、他の立体もワイヤフレームで描画できます。
ただし、Draw_Polygon 関数はポリゴンが四角形であるものとして作ってあります。例えばピラミッドや角錐のように、三角形のポリゴンが入る立体は正常に描画できません。
三角形を描画できるようにするには、

 //四角形の左上の頂点から右回りに線を引く
 for( j = 1 ; j <= 3 ; j++ )

この部分を

 for( j = 1 ; j <= 2 ; j++ )

とします。頂点が減った分、線を引くループの回数を減らすということです。
 
ピラミッドは、底面が四角形、側面が三角形です。
四角形と三角形の描画関数を別々に作ると面倒ですから、底面を四角形のポリゴンではなく、対角線で分割した三角形2枚と考えます。これなら、三角形を描画する関数だけで済みます。
三角形は最も基本的な多角形で、全ての多角形はいくつかの三角形に分割できる点を利用した考え方です。
頂点が増えるため計算時間が増えるところが難点ですが、四角形と三角形が混在すると頂点データの持ち方も複雑になることから、全て三角形のポリゴンとして描画する3DCGソフトもあります。
複雑な立体を描画するなら、共有する頂点は計算しないといった、高速化を図る工夫も必要になってきます。
まあ、あまり複雑なものは Flash ではなく、3DCGソフトで作った方が早いですね。


余談ですが。
ファイルサイズが軽ければ処理も軽いとは限りません。
今回の作例はスクリプトだけなのでファイルサイズは小さいですが、三角関数や乗算といった複雑な計算を何回もやらせたり、巨大な配列を使ってメモリを消費していますので、処理はそれなりに重いです。
(更に複雑な3DCGもホイホイと描画できる今時のパソコンなら、大した負担ではありませんが・・・)
また、外部から画像を多数読み込むようなムービーは、ムービー本体の容量は軽いですが、読み込まれた画像がメモリを占有してしまい、読み込む画像が多すぎると、システムが遅くなるなどの深刻な症状が発生するほどの重いムービーになりかねません。
もっとも、ファイルが大きければ、それだけ最初からメモリやシステムリソースを大量に占有するということですので、一般的には処理は重いです。

ワイヤフレームのアニメや、計算で描画するCGの考え方は昔からあります。
ただ、お粗末な演算能力のCPUと、何キロバイトという程度の少ないメモリしか積んでいなかったパソコンでは計算に時間がかかりすぎて、実用的ではなかっただけです。


今回はさしあたって、”立方体を回転して、ワイヤフレームで描画する”という、これ1つで完結したムービークリップをご紹介しました。
もう少し構造を整理すると、任意のポリゴンデータをワイヤフレームで表示するといった、汎用性の高いシンボルにもできますが、これはまたの機会にでも考えてみてください。
とりあえず、無事に表示して、いろいろ回転してみてください。
本来は2Dの絵しか扱えないできない Flash で3Dっぽい絵が表示できるというのは、ちょっと感動ですよ。

またまた長くなってすみませんでした。

投稿日時 - 2005-06-15 17:35:27

お礼

お返事が遅くなってしまい申し訳ありませんでした。

2度のアドバイスありがとうございます。
やはりメインのタイムラインにかいていた事が原因でした^^;
今度はちゃんと真ん中に表示されるようになったので安心しました。
回転角度の設定も簡単にできるという事で、自分なりにいろいろ研究してみたいと思います。

投稿日時 - 2005-06-16 23:21:14

ANo.1

私は「数学キライ~~!」という人です。
正六面体だと,頂点は8つあるわけで,その点を線で結べば良いわけですよね(ここまでは多分,算数)。
線を結ぶのは簡単なのですが,動く座標を計算できないのですよ。

そんなわけで,半分モーショントィーンで,半分スクリプトで動くものを考えてみました。

    A3
  /   \
A4      A2
| \   /|
|   A1  | 
B4   |  B2
  \ | /
    B1

↑壊れていますが六面体を斜め上から見た図。
(B3は描けませんでした。)

頂点A1→A2,頂点A2→A3 ……
頂点B1→B2,頂点B2→B3 ……
と左から右に回転する場合を考えます。

多分,A1→A2→A3→A4→A1 という動き(軌跡)は楕円だと思うのです(違っていたらすみません)。

そういうわけで,タイムラインにガイドレイヤーを追加して,そのガイドレイヤーに楕円を描きます。
それでその下にレイヤーを4つ用意して,A1~A4というインスタンス名の小さい黒丸のムービークリップを楕円上の位置に配置します。B1→B2→B3→B4→B1に関しても同様に作成。
それで10フレームくらいにして,A1~B4のMC(ムービークリップ)のある最終フレームをキーフレームにして,
A1ならA2の少し手前,A2ならA3の少し手前,…というふうに配置し,
各MCのある1フレーム目を選択,モーショントゥイーンを作成します。

わかりますかね。
文字だけだとすんごくわかりにくいですよね。
つまり 『4分の1回転するアニメ』 を作成しようとしているのです。
タイムラインを図示するとこんな感じ。

^ガイド:レイヤー ・・■|●                 |<楕円>
  □レイヤー   ・・■|●>-------------→|●|<A1>
  □レイヤー   ・・■|●>-------------→|●|<A2>
  □レイヤー   ・・■|●>-------------→|●|<A3>
  □レイヤー   ・・■|●>-------------→|●|<A4>
^ガイド:レイヤー ・・■|●                 |<楕円>
  □レイヤー   ・・■|●>-------------→|●|<B1>
  □レイヤー   ・・■|●>-------------→|●|<B2>
  □レイヤー   ・・■|●>-------------→|●|<B3>
  □レイヤー   ・・■|●>-------------→|●|<B4>

 『4分の1回転するアニメ』 をループさせれば,1回転でも2回転でもするわけです。

以上で,8点のMCが動くアニメができると思います。
次に,これらの点を線でつなぎます。

1フレーム目にフレームアクションとして以下のスクリプトを書きます。
-----------------------------------
this.onEnterFrame = function() {
// 前に描いた線を消す
this.clear();

// 線の設定(太さ1,色00000000(黒))
this.lineStyle(1, 0x000000);

// 上面の4点をつなぐ線を引く
this.MoveTo(A1._x, A1._y);
this.lineTo(A2._x, A2._y);
this.lineTo(A3._x, A3._y);
this.lineTo(A4._x, A4._y);
this.lineTo(A1._x, A1._y);

// 下面の4点をつなぐ線を引く
this.MoveTo(B1._x, B1._y);
this.lineTo(B2._x, B2._y);
this.lineTo(B3._x, B3._y);
this.lineTo(B4._x, B4._y);
this.lineTo(B1._x, B1._y);

// 縦をつなぐ線を引く
this.MoveTo(A1._x, A1._y);
this.lineTo(B1._x, B1._y);
this.MoveTo(A2._x, A2._y);
this.lineTo(B2._x, B2._y);
this.MoveTo(A3._x, A3._y);
this.lineTo(B3._x, B3._y);
this.MoveTo(A4._x, A4._y);
this.lineTo(B4._x, B4._y);
};
----------------------------------

これでできあがり。
実際に作ってみたところ,SWFは984 バイト。1KB未満でできました。
バイト数と動きの重さは全く関係ないですが,動きも軽いですよ。

インスタンス名A1~B4はすべて_rootに作ってあるという仮定のスクリプトです。
_rootにない場合は,ターゲットへのパスが必要です。

でもなんか,形が若干変です。
軌跡は楕円ではないのでしょうかね。いや楕円だと思いますが…。
ガイドラインの微調整が必要かもしれません。

Flash5までは,サイコロの回転はひたすら,シェープトゥイーンで作成していたと思います。
シェープトゥイーンではなくモーショントゥイーンであるぶん,だいぶん軽くだいぶん簡単に作れると思います。

投稿日時 - 2005-06-14 12:13:51

お礼

図を交えての御回答ありがとうございます。
モーショントゥイーンとスクリプトの合わせ技で1KB未満に収まるとは驚きですね。

バイト数と動きの重さは全く関係ないですか、これも初めて知りました。
ムービープレビュのメニューの中に、ダウンロード速度を設定する項目があるので、サイズと動作の重さは比例するものかと思っていましたが、どうやら間違った思い込みをしていたようです^^;

さっそく、この方法で試してみたいと思います。
ありがとうございました。

投稿日時 - 2005-06-15 10:42:05

あなたにオススメの質問