Luaレッスン27「(3.2)物理エンジンへようこそ(その5)」和訳

出典:http://compasstech.com.au/TNS_Authoring/Scripting/script_tut27.html

レッスン27「(3.2)物理エンジンへようこそ(その5)」:物理オブジェクトとしての多角形

前回のレッスンでは、セグメントを操作するためのコマンドを紹介しました。今回は、多角形にまでレパートリーを拡げます。

function init(gc)

     ...

     local angleDelta = 360/nvertices

     local angle = 0

     vertices = { }

     for i=1,nvertices do

          table.insert(vertices, 1,

          physics.Vect(math.cos(math.rad(angle))*radius,

          math.sin(math.rad(angle))*radius))

          angle = angle + angleDelta

     end

     inertia = physics.misc.momentForPoly(

     mass, vertices, physics.Vect(0,0))

     for i=1,totalBodies do

          newBody = physics.Body(mass, inertia)

          newShape = physics.PolyShape(newBody, vertices, physics.Vect(0,0))

          ...

     end

     function paint(gc)

          bounds(W, H)

          for _,shape in ipairs(shapes) do

               local pointcount = 1

               points = shape:points()

               for _,point in ipairs(points) do

                    vertexpoints[pointcount] = point:x()

                    vertexpoints[pointcount] = vertexpoints[pointcount] < W

                    and vertexpoints[pointcount] or W

                    vertexpoints[pointcount] = vertexpoints[pointcount] > 0

                    and vertexpoints[pointcount] or 0

                    vertexpoints[pointcount+1] = point:y()

                    vertexpoints[pointcount + 1] = vertexpoints[pointcount + 1] < H and vertexpoints[pointcount + 1] or H

                    vertexpoints[pointcount + 1] = vertexpoints[pointcount + 1] > 0 and vertexpoints[pointcount + 1] or 0

                    pointcount = pointcount + 2

               end

               gc:setColorRGB(math.random(255), math.random(255), math.random(255))

               gc:fillPolygon(vertexpoints)

               gc:setColorRGB(0)

               gc:drawPolyLine(vertexpoints)

          end

          ...

 

  1. 多角形を弾ませる、くるくる回す

我々の作成している物理ライブラリーに多角形を取り込む作業は驚くほど容易です。特殊なコマンドを2つ使うだけで、シェイプを多角形として認識することができます。1つは、physics.PolyShape(body, vertices, offset)というPolyShapeコマンドです。もう1つは、physics.misc.momentForPoly(mass, vertices, offset)という慣性定義です。

  • physics.PolyShape(body, vertices, offset)
  • physics.misc.momentForPoly(body, vertices, offset)

Polygonシェイプは、一連のライン・セグメントで繋がれます。多角形で囲われる部分は凸状でなければならず、その各頂点は反時計回りに定義しなければなりません。

これが、今回のレッスンで使う正多角形の定義につながります。

頂点用のverticesテーブルがベクトル・ペアから構築されることがわかるでしょう。この方法なら、各頂点のxy座標が1回で追加され、テーブル(リストではなく行列)が生成されます。ここでは、table.insertコマンドにもう1つ、数字の1を引数として追加します。こうすれば、各ベクトルがテーブルの最初の要素として追加されます。これで、反時計回りに定義されるようになります。

もちろん、頂点ペアを格納するこのリストは、このままでは、シェイプをペイントするのに使うdrawPolyLineコマンド、fillPolygonコマンドにはうまく適合しません。paint函数に追加するコード部分をよく見てください。

 

  1. 多角形をペイントする

まず、ページの境界を構成する壁をペイントします。そのあと、先に定義しておいたシェイプのxy座標にそれぞれの多角形シェイプを割り当てるという方法で多角形シェイプをペイントする処理を開始します。

最初のforループで、shapesテーブルに格納してある各シェイプが巡回されます。ここでもやはり、テーブルの各メンバーにインデックス付けをおこなうダミー変数ペアと組み合わせてipairsコマンドを使用していることに注意してください。

最初のシェイプの最初のポイントのx座標を最初の頂点に割り当てたら、このポイントが4つの壁の内側に来るようにします。同じことをy座標についても行い、あとは最初のシェイプの各頂点を順番に処理してゆきます。ついで、各シェイプについて順番に処理してゆきます。

ここでおこなっていることは、多角形を描くのに必要な作業として、各ポイントから成る行列verticesを、zy座標から成るvertexpointsリストに変換することです。

この処理については、順を追いながらじっくり考えてみてください。

最終的には、いつもの方法で、それぞれにランダムな色で多角形の描画と色塗りができます。

バージョン3.2では、たった1つの数字でgc:setColorRGBが使えるようになりました。以前なら、赤、緑、青のそれぞれに別々の数字が必要でしたね。

paintコマンドの残りの部分は、フローティング・ボタンを作成する手段として、提供された画像を使用しているだけです。それに続く各函数は、マウス、矢印キー、enter、escapeといった操作子を定義しています。いずれの操作子も、いずれも、サンプル・ファイルでは、分割されたジオメトリー・ウィンドウのスライダーとリンクしています。ハンドヘルドでもPlayerでもドキュメントがうまく動作するようにするためです。

これで、少なくともわたくしにとってはエキサイティングな学習の旅であった最終地点へ到達しました。何か御質問、提案、建設的批判がおありでしたら、是非お聞かせください。

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

(訳註)今回の実行例。スクリプトはサンプル・ファイルのまま。

f:id:ti-nspire:20141226122415g:plain