qml-box2dを使ってみよう

#はじめに

さて、Advent Calendarも無事に８日目を迎えました。昨日はasobotさんによるQt CreatorのRC版の情報でした。新しいリリースバージョンが出てくるのが楽しみですね。

さて、今回のカレンダーはここまでQMLを扱ったエントリーなしという驚愕の事実に気がつきまして、本日はQML関係としまして、**qml-box2d**を*かる〜く*ご紹介しておきます。hermit4は、普段QML自体もほとんど使う事がない初心者ですので、色々と間違いもあるかと思います。何か気がつかれた方はコメント下さい。

# 基礎知識
##QMLとは

QMLはQtを使って実装された宣言型UI記述言語です。

```qml:MainForm.ui.qml
import QtQuick 2.4

Rectangle {
    property alias mouseArea: mouseArea

    width: 360
    height: 360

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Text {
        anchors.centerIn: parent
        text: "Hello World"
    }
}
```

```qml:main.qml
import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }
    }
}
```

このコードは、QMLアプリケーションのプロジェクトを新規作成すると生成されるコードです。MainFormは、Rectangle(長方形）の中にMouseAreaというマウスのイベントを取得可能な見えない領域と、Hello Worldの文字を生成しています。main.qmlでは、Windowの中にMainFormを一つ用意しており、マウスのクリック時に動作を終了するよう定義しています。

上記のような宣言構文で画面上の配置を行い、動作をJavaScriptで定義できるほか、C++で記述した拡張ライブラリを登録して利用する事もできます。

Qtプロジェクトでは、標準ライブラリのQt QuickモジュールとQt Widgetのような標準的なGUIアプリのコントロールを提供するQt Quick Controlsモジュールの２つのライブラリが用意されています。上記の例では、QtQuickモジュールを利用しています。

日本語では、22日目に記事を書いて下さる予定のIoriAyane(折戸さん）による「Qt QuickではじめるクロスプラットフォームUIプログラミング」という書籍が販売されています。QML/Qt Quick初期の頃のものなので、そのままでは色々素直に動かなかったりはしますが、Qtに付属のチュートリアルやサンプルと合わせて、なぜ動かないかも含めて調べていくと、きっといつの間にかQMLが使いこなせるようになるかと思います。

##[Box2D](http://www.box2d.org/)とは 
昨年のQt Advent Calendarの13日目にyasukikudanさんが、「[QGraphcsViewでBox2Dを表示する](http://qiita.com/yasukikudan/items/930e31e5f814bb2313c0)」というエントリーを登録して下さっています。まぁ、細かい説明なしのシンプルなものなので、なんぞこれって思った方もいるかもしれません。

Box2Dは、2次元上での物理演算エンジンで、ある重力下での質量、速度、摩擦といった力学計算を行ってくれるゲーム用のエンジンです。スマートフォンでゲームをたしなむ方ですと、Angry Birdsの動作演算に利用されているものだといえば、なんとなく想像がつくかもしれません。

元々はC++で作られたものですが、C#, JavaScript, Python, ActionScript等に移植されている人気のエンジンです。
実際、どういう事が出来るのかは、このあとqml-box2dの使い方で見ていきたいと思います。

#qml-box2d
## QML Box2Dについて
QMLはC++で拡張することができると述べましたが、qml-box2dもその一つで、C++で実装されたBox2DをQML上で動作できるように改良したQMLモジュールライブラリです。現在、[GitHub](https://github.com/qml-box2d)にて公開されています。

## Install方法
本日は時間もない[^1]ので、Advent Calendarも乱立するご時世に、わざわざQtを見に来られているので、既にQtの環境はお持ちかと思います。ついでに、Git環境も既に整っているという前提で話を進めてしまいます。わからなければ、コメント残して下さい。あとで手直しします。

```shell-session:
$ git clone https://github.com/qml-box2d/qml-box2d.git
$ cd qml-box2d
$ qmake
$ make
$ make install
```

Windows環境の場合は、Qtメニューからたどれるコマンドプロンプトを開き、環境に応じてvcbarsall.batを通した後、makeの代わりに<Qt Dir>\Tools\QtCreator\bin\jom.exe を使うと素直にビルドできました。なお、Qtのinstall環境によっては、make installは管理者権限が必要な場合もあります。

make installを実施すると、Qtに、qml-box2dのライブラリがinstallされます。

```shell-session:
 例えば、Mac OS X の場合は、イカの通り
./Qt5.5.1/5.5/clang_64/qml/Box2D.2.0/libBox2D.dylib
./Qt5.5.1/5.5/clang_64/qml/Box2D.2.0/qmldir
```

## 動作検証
qml-box2dもexampleが色々用意されていますので、まずはそちらを動かしてみましょう。

```shell-session:
$ qmlscene <path to qml-box2d>/examples/boxes/boxes.qml
```

上から３つの箱が落ちてくるだけのシンプルなアプリが実行されるかと思います。
![boxes.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/a3bfcfa5-587c-8f10-ba01-eb0a77d9c9c5.gif)

## 概要説明
最初にサンプルの内容を説明しよう・・・と思ったのですが、これがまた意外と量が多いので余計にわかりにくくなりそうです。というわけで、まずは、qml-box2dのソースコードを見てみましょう。

```cpp:box2dplugin.cpp
void Box2DPlugin::registerTypes(const char *uri)
{
#if !defined(STATIC_PLUGIN_BOX2D)
    Q_ASSERT(QLatin1String(uri) == QLatin1String("Box2D"));
#endif

    qmlRegisterType<Box2DWorld>(uri, versionMajor, versionMinor, "World");
    qmlRegisterUncreatableType<Box2DProfile>(uri, versionMajor, versionMinor, "Profile",
                                             QStringLiteral("Property group of World"));
    qmlRegisterType<Box2DBody>(uri, versionMajor, versionMinor, "Body");
    qmlRegisterUncreatableType<Box2DFixture>(uri, versionMajor, versionMinor, "Fixture",
                                             QStringLiteral("Base type for Box, Circle etc."));
    qmlRegisterType<Box2DBox>(uri, versionMajor, versionMinor, "Box");
    qmlRegisterType<Box2DCircle>(uri, versionMajor, versionMinor, "Circle");
    qmlRegisterType<Box2DPolygon>(uri, versionMajor, versionMinor, "Polygon");
    qmlRegisterType<Box2DChain>(uri, versionMajor, versionMinor, "Chain");
    qmlRegisterType<Box2DEdge>(uri, versionMajor, versionMinor, "Edge");
    qmlRegisterType<Box2DDebugDraw>(uri, versionMajor, versionMinor, "DebugDraw");
    qmlRegisterUncreatableType<Box2DJoint>(uri, versionMajor, versionMinor, "Joint",
                                           QStringLiteral("Base type for DistanceJoint, RevoluteJoint etc."));
    qmlRegisterType<Box2DDistanceJoint>(uri, versionMajor, versionMinor, "DistanceJoint");
    qmlRegisterType<Box2DPrismaticJoint>(uri, versionMajor, versionMinor, "PrismaticJoint");
    qmlRegisterType<Box2DRevoluteJoint>(uri, versionMajor, versionMinor, "RevoluteJoint");
    qmlRegisterType<Box2DMotorJoint>(uri, versionMajor, versionMinor, "MotorJoint");
    qmlRegisterType<Box2DWeldJoint>(uri, versionMajor, versionMinor, "WeldJoint");
    qmlRegisterType<Box2DPulleyJoint>(uri, versionMajor, versionMinor, "PulleyJoint");
    qmlRegisterType<Box2DFrictionJoint>(uri, versionMajor, versionMinor, "FrictionJoint");
    qmlRegisterType<Box2DWheelJoint>(uri, versionMajor, versionMinor, "WheelJoint");
    qmlRegisterType<Box2DMouseJoint>(uri, versionMajor, versionMinor, "MouseJoint");
    qmlRegisterType<Box2DGearJoint>(uri, versionMajor, versionMinor, "GearJoint");
    qmlRegisterType<Box2DRopeJoint>(uri, versionMajor, versionMinor, "RopeJoint");
    qmlRegisterType<Box2DRayCast>(uri, versionMajor, versionMinor, "RayCast");

    qmlRegisterUncreatableType<Box2DContact>(uri, versionMajor, versionMinor, "Contact", QStringLiteral("Contact class"));
}
```

QMLで利用できる型として定義をしているのが上記のメソッドです。

* World
* Body
* [UncreatableType] Fixture  
     * Box  
     * Circle  
     * Polygon  
     * Chain  
     * Edge  
* DebugDraw
* [UncreatableType] Joint
    * DistanceJoint
    * PrismaticJoint
    * RevoluteJoint
    * MotorJoint
    * WeldJoint
    * PullyJoint
    * FrictionJoint
    * WheelJoint
    * MouseJoint
    * GearJoint
    * RopeJoint
* RayCast
* [UncreatableType] Contact
### World
シミュレーション上の１つの世界を表します。

* 重力の設定
* 物理シミュレーションの調整
* 指定領域のFixtureの検出
* 衝突検出と交錯したFixtureの検出

といった機能を持ちます。プロパティグループとして*Profile*を保持しています。

### Body
物理演算上の基本オブジェクト。ただしこれ自体が衝突したり、跳ねたりする”物”を表しているのではなく、演算上のプロパティに過ぎない。だったらBodyという命名をするなって突っ込みを入れたくなりますよね。

* 質量
* 速度
* 回転慣性
* 角速度
* 場所
* 角度

といった特性を保持します。

### Fixture
物理演算上で、物質の形状、大きさ、材質特性を保持します。Bodyに対して割り当てられるもので、FixtureをもったBodyが衝突や、バウンドする演算対象の物質となります。

* 形状(円や多角形）
* 衝突特性（どう弾むのか）
* 摩擦
* 密度（重さ）

といった特性を保持します。QMLでは、Fixtureは、以下のような種類が用意されています。

* Box
* Circle
* Polygon
* Chain
* Edge

### DebugDraw
box2dは物理演算エンジンで、描画エンジンではないため、演算結果の数値が求められるだけで、通常は描画しません。DebugDrawは、物理演算のデバッグ用に演算結果を画面上に描画する機能を提供します。

### Joint
Body間の制約条件を示すもので、物質同士がどのような関係で存在しているのかという状態をしめします。たとえば固く溶接されているのか、ヒンジのようなもので接続されているのか、そういった関連性をJointで定義します。種類としては、以下のものが用意されています。

* DistanceJoint
* PrismaticJoint
* RevoluteJoint
* MotorJoint
* WeldJoint
* PullyJoint
* FrictionJoint
* WheelJoint
* MouseJoint
* GearJoint
* RopeJoint

### RayCast
レイキャストは、衝突判定のため、光線のようにまっすぐ伸びる仮想的な線を利用して衝突を判定するための機能を提供しています。

```qml:
RayCast {
    maxFraction:
}
```

### Contact
box2dはゲームエンジンですので、衝突の結果として、物体の消滅、破損、サウンド効果等を与える必要があります。Contactは物体の衝突について、どう扱うかの定義を行うための機能を提供しています。

## シンプルな例
exampleの中に色々入ってはいますが、最初の一歩としては大きすぎるので、簡単なものを作ってみましょう。
テキストエディタか何かで、以下のコードを書いてみて下さい。

```qml:simple.qml
import QtQuick 2.4
import QtQuick.Window 2.2
import Box2D 2.0

Window {
    visible: true
    width: 640
    height: 480
    Rectangle {
        id: screen
        anchors.fill: parent
        World { 
            id: physicsWorld 
        }

        DebugDraw {
            visible: true
        }

        Body {
            world: physicsWorld
            bodyType: Body.Dynamic
            Box {
                x: screen.width/2
                y: 10
                width: 10
                height: 10
            }
        }
    }
}
```

編集が終わったら、qmlsceneで実行してみましょう。

```shell-session:
$ qmlscene simple.qml
```
![simple.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/e9ccbdbb-57b4-64b4-275d-308602ad6109.gif)

四角い形状の何かが、画面の上から下へ落ちて行ったかと思います。

DebugDrawを使って、演算結果を画面表示しているのは、Body+Box(Fixture)は、演算の為の形状であって描画対象ではないため、DebugDrawを通さないと画面に何も表示されないからです。
それでは、DebugDrawを外して画面上に表示させるのにはどうしたらよいかというと、表示対象の物を用意してあげる必要があります。

```qml:simple2.qml
import QtQuick 2.4
import QtQuick.Window 2.2
import Box2D 2.0

Window {
    visible: true
    width: 640
    height: 480
    Rectangle {
        anchors.fill: parent
        World { 
            id: physicsWorld 
        }

        Rectangle {
            id: rectangle
            x: parent.width/2
            y: 10
            width: 10
            height: 10
            color: "red"
            Body {
                id: boxBody
                target: rectangle
                world: physicsWorld
                bodyType: Body.Dynamic

                Box {
                    id: box
                    x: rectangle.x
                    y: rectangle.y
                    width: rectangle.width
                    height: rectangle.height
                }
            }
        }
    }
}
```
描画対象となるRectangle(id=rectangle)を用意し、Bodyはtargetをrectangleとして、その移動を演算して反映させるようにします。これで、rectangleは、box2dの演算結果に基づいて、Body+Boxと同様に画面上を落下していくことになるのです。

![simple2.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/0c4a2062-a303-58f2-73ac-5e8336d862cf.gif)

実際、何をどう使うと、どんなことができるのかという事は、exampleを一つずつ見ていくのが良いかと思います。


# まとめ
本日は、QMLに２D空間での物理演算エンジンであるbox2dを組み合わせたqml-box2dライブラリについてご紹介致しました。ゲームを作ろうとすると、物理演算が必要になってくるわけですが、コレを使うとずいぶんと楽になりそうですね。

なにぶん、十分な時間もなく書き付けている(本日終了３０分前にまだ書いてる）ので、ごちゃごちゃしていてすいません。明日は、informationseaさんによる、Windows環境でのStatic版Qtのビルド方法だそうです。お楽しみに。


# Appendix.A qml-box2d Examples
ui.qmlをqmlsceneで見れば、選択メニューで一覧できるようですが、一通りのせておきます。

## 共有アイテム
実装を簡略にするためによく使う機能を名前を付けて使い回せるようにしている

* shared/BoxBody.qml  
  Body + Box Fixtureの組み合わせ
* shared/ChainBody.qml  
  Body + Chain Fixtureの組み合わせ
* shared/CircleBody.qml  
  Body + Circle Fixtureの組み合わせ
* shared/EdgeBody.qml  
  Body + Edgeの組み合わせ
* shared/ImageBoxBody.qml  
  BoxBodyにImageという画像描画を組み合わせたもの
* shared/PhysicsItem.qml  
  Body + Itemの組み合わせ。
* shared/PolygonBody.qml  
  Body + Polygon Fixtureの組み合わせ
* shared/RectangleBoxBody.qml  
  BoxBodyにRectangleという描画領域を組み合わせたもの
* shared/ScreenBoundaries.qml  
  演算対象物が領域外に抜けて行かないようにするためのボーダーを用意するためのもの。

## 実装例
### - accelerometer/accelerometer.qml
![accelerometers.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/6bfe9f14-5e4d-151d-82af-7de47bc7a468.gif)

BoxesにQMLのAccelerometerを組み合わせたもの。
### - boxes/boxes.qml
動作検証時に使ったサンプル。
### - cannon/main.qml
![canon.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/1dc479b6-ed5c-31eb-3b6f-5ab9254657e1.gif)

大砲をうつというゲームっぽい作りのもの。
なお、画像ではわかりませんが、Shoot時に発射音も出しています。
### - contacts/main.qml
ベルトコンベアと吸い込み・吐き出しといった動作にくわえ、吐き出された時に色が変わるといったプロパティ変化もついています。

サイズ圧縮の関係でGif画像はせわしないですが、もっとゆっくり動作してます。
![contacts_s.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/2690b4c2-c168-3629-6fa6-befbc88212eb.gif)

### - demolition/demolition.qml
マウスのクリックで弾け飛ぶboxが並んでいます。ぴょんぴょんしているのは、hermit4が適当にクリックしているからです。
![demolition.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/737f1173-2b97-ba10-7ad2-183bca011254.gif)

### - distance/distance.qml
Joint関連のサンプルですかね。マウスをクリックすると位置によりカラフルな円が回転しながら動作し、それに引っ張られて後ろの長方形も移動します。画像だとちょっとわかりにくいので、実際のサンプルを動かしてみて下さい。

![distance.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/0899c84b-a893-fac5-21a9-1f825c37fd61.gif)

### - filtering/filterling.qml
落下したカラフルなボックスのうち、同じ色は重なるデモです。
![filtering.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/35d0cbba-d698-4140-4340-694f681a77c6.gif)

### - fixtures/main.qml
それぞれのFixtureの例
![fixtures.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/f0db66d5-e914-57bf-6208-20accab5b9d2.gif)

### - friction/main.qml
ぶつかった時の動作に関するサンプル

![friction.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/280588d3-4aef-bf76-e542-83be8686118a.gif)

### - gear/main.qml
回転体や、重さで開くゲート、動作するゲートなど動くものとの接触などのサンプルでしょうか。
画像を小さくする上でだいぶ早くなっているので、何がなんだかわかりにくいですが・・・。

![gear.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/f177a9ea-130f-c817-0fc5-14d44efd1a5f.gif)

### - impulse
落下したものが弾むサンプル
![impulse.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/db9eb5d1-5b89-de7a-9fd6-83023f91c0d0.gif)

### - monera/monera.qml
マウスが触れると移動しながらメッセージを表示するサンプル
![monera.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/4773cc52-595d-720b-10f2-3c0e0420ff52.gif)

### - motorjoint/boart.qml
MortorJointの例。波間をゆらゆらとボートが揺れるような動きが実装できる。
![motorjoint.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/25ffa025-3c81-b4d7-1baa-b278f7219d59.gif)

### - mouse/main.qml
Mouseで操作可能なボックスの例でしょうか。マウスでドラッグすると物体を放り投げられます。
![mouse.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/54468fa7-d476-4bba-3b27-947e467c7153.gif)

### - movingBox/movingBox.qml
キーボードのカーソルキーで赤い四角形を動かすサンプルです。
![movingBox.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/3ac2f3b3-a4aa-8e44-e48d-970d275a3d4c.gif)

### - polygons/polygons.qml
Polygons Fixtureのサンプル
![polygons.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/b032edea-a137-60e8-a9ed-58b4a0e5aa91.gif)

### - prismatic/prismatic.qml
PrismaticJointのサンプル
![prismatic.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/ed362560-cfac-d0ce-d03f-1481b3e31083.gif)

### - pulley/main.qml
PullyJointのサンプル
![pully.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/847af1b0-0f8a-53cf-68ea-28e824ba0f18.gif)

### - raycast/main.qml
RayCastのサンプル
![raycast.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/e070dc4c-95d6-1474-2048-500401bc35c6.gif)

### - revolute/revolute.qml
RevoluteJointのサンプル。マウスのクリックで停止、カーソルキーの左右で動く方向や勢いが変えられます。
![revolute.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/2aecacae-eae8-02fb-5150-9b068d8e810c.gif)


### - rope/main.qml
RopeJointのサンプル。これはみたままでわかりやすいですね。
![rope.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/0cdb1306-a324-c7f7-38b1-88f16c600cc5.gif)


### - weld/main.qml
WeldJointのサンプル
![weld.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/84e89b59-2838-c785-9c43-97d3ade95426.gif)

### - wheel
WheelJointのサンプル
![wheel.gif](https://qiita-image-store.s3.amazonaws.com/0/58828/b2990146-6d4f-7f79-ceee-2dec7c14f2a1.gif)


# Appendix.B qml-box2d プロパティ
それでは、各タイプについてプロパティを抜き出していってみます。ただの羅列でごめんなさい。そのうちキチンと調べてまとめたいと思います。

## World
```qml:
World {
    running:
    timeStep:
    velocityIterations:
    positionIterations:
    gravity:
    autoClearForces:
    pixelsPerMeter:
    profile:
    enableContactEvents:
}

Profile {
    step:
    collide:
    solve:
    solveInit:
    solveVelocity:
    solvePosition:
    broadphase:
    solveTOI:
    synchronize:
    emitSignals:
}
```

## Body

```qml:
Body {
    world:
    target:
    linearDamping:
    angularDamping:
    bodyType:
    bullet:
    sleepingAllowed:
    fixedRotation:
    active:
    awake:
    linearVelocity:
    angularVelocity:
    fixtures:
    gravityScale:
}
```

## Fixture

```qml:
Box {
    // Fixture共通
    density
    friction
    restitution
    sensor
    categories
    collidesWith
    groupIndex

    // Box用
    x
    y
    width
    height
    rotation
}

Circle {
    density
    friction
    restitution
    sensor
    categories
    collidesWith
    groupIndex
    x
    y
    radius
}

Polygon {
    density
    friction
    restitution
    sensor
    categories
    collidesWith
    groupIndex
    vertices
}

Chain {
    density
    friction
    restitution
    sensor
    categories
    collidesWith
    groupIndex
    vertices
    loop
    prevVertex
    nextVertex
}

Edge {
    density
    friction
    restitution
    sensor
    categories
    collidesWith
    groupIndex
    vertices
}
```

## Joint

```qml:
DistanceJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:

    localAnchorA:
    localAnchorB:
    length:
    frequencyHz:
    dampingRatio:
}

PrismaticJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:

    localAnchorA:
    localAnchorB:
    localAxisA:
    referenceAngle:
    enableLimit:
    lowerTranslation:
    upperTranslation:
    enableMotor:
    maxMotorForce:
    motorSpeed:
}

RevoluteJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:

    localAnchorA:
    localAnchorB:
    referenceAngle:
    enableLimit:
    lowerAngle:
    upperAngle:
    enableMotor:
    motorSpeed:
    maxMotorTorque:
}

MotorJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    linearOffset:
    angularOffset:
    maxForce:
    maxTorque:
    correctionFactor:
}

WeldJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:

    referenceAngle:
    frequencyHz:
    dampingRatio:
    localAnchorA:
    localAnchorB:
}

PullyJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    groundAnchorA:
    groundAnchorB: 
    localAnchorA:
    localAnchorB:
    lengthA:
    lengthB:
    ratio:
}

FrictionJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    localAnchorA:
    localAnchorB:
    maxForce:
    maxTorque:
}

WheelJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    localAnchorA:
    localAnchorB:
    localAxisA:
    dampingRatio:
    frequencyHz:
    maxMotorTorque:
    motorSpeed:
    enableMotor:
}

MouseJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    target:
    maxForce:
    frequencyHz:
    dampingRatio:
}

GearJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    joint1:
    joint2:
    ration:
}

RopeJoint {
    JointType:
    collideConnected:
    bodyA:
    bodyB:
    localAnchorA:
    localAnchorB:
    maxLength:
}
```

## Contact

```qml:
Contact {
    enabled:
    fixtureA:
    fixtureB:
    childIndexA:
    childIndexB:
    friction:
    restitution:
    tangentSpeed:
}
```

# 注釈
[^1]: Macがハングアップしてまともに動作しなくなり格闘してました。ふと気が付いてカスペルスキーさんを止めたら動いた・・・