この記事は何か?
前回からの続きです。
実行環境などに変更はありません。
この投稿では、「簡単なシーン」ページのコードを解説します。
コードを読み解く
このページにも、ふたつのファイルが存在します。
- メインファイル
- SharedCode(以前のページと同じもの)
ここでは、メインファイルを主に扱います。
メインファイル
まず、行っていること全体を挙げます。
- 変数に3Dモデルを割り当てる
- シーンに3Dモデルを追加する
- シーン開始時の演出
- カメラのイベントを指定する
大まかには以上の4つが行われています。
全体のコードを見たあと、ひとつずつ解説します。
// いくつかのモデルを作成します。
var raincloud = Model.raincloud
var label = Model.text("雨の日 (´・_・`)", elevation: 10.cm)
var cactus = Model.cactus
// シーンに複数のモデルを追加します。
scene.add([raincloud, label, cactus])
// シーンが開始するときに、サウンドを再生して雨雲から雨を降らせます。
scene.setOnStartHandler {
scene.applyColor(scheme: .cool)
raincloud.play(.soundscapeLoop, loops: true)
raincloud.animate(.rain)
raincloud.run(action: .scaleTo(3, duration: 5))
}
// カメラがサボテンから8cm以内に近づいたとき、太陽を昇らせます!
scene.camera.when(cactus, isWithin: 8.cm) {
scene.applyColor(scheme: .hot)
raincloud.remove()
label.text = "晴れの日! (^_^)"
let sun = Model.sun
scene.place(sun, at: cactus.location)
sun.run(group: [.moveBy(x: 0, y: 20.cm, z: 0, duration: 5), .scaleBy(5, duration: 10)])
sun.animate()
}
変数の宣言
以下に挙げる3つのモデルを生成しています。
- raincloud(雨雲)
- label(テキスト)
- cactus(サボテン)
var raincloud = Model.raincloud
var label = Model.text("雨の日 (´・_・`)", elevation: 10.cm)
var cactus = Model.cactus
ここで気になるのは、raincloud
とcactus
モデルを作成しているコードがメソッドではなく、プロパティである点です。
Model
型のraincloud
プロパティが3Dモデルを返すという記述になっています。
一方、label
モデルはModel
型のtext(_:elevation:)
メソッドによって作成されています。
いずれにしても、オブジェクトを作成するためにイニシャライザが呼び出されていません。
Swift Playgrounds特有のアプローチに見えます。
これらのモデルは、scene
オブジェクトのadd()
メソッドによってAR空間に配置されます。
なお、label
モデルは、サーフェスのタップした面から10cm高いところに表示されます。
scene.add([raincloud, label, cactus])
add()
メソッドを使用しているので、ページを実行したあと検出したサーフェスをタップすることで、任意の場所にモデルを配置できます。
パラメータがモデルの配列になっているので、連続的にシーンに配置できます。
ここでは、3回タップすることになります。
シーン開始時のハンドラ
ページを実行すると、サーフェスの検出が始まります。
サーフェスをタップして、すべてのモデルが配置されると「シーンを開始」ボタンを押せるようになります。
ここでは、シーン開始後に以下の演出が始まるようにしています。
- シーン全体を冷淡な雰囲気にする
- BGMを鳴らす
- 雨雲から雨を降らせる
- 雨雲を徐々に大きくする
scene.setOnStartHandler {
scene.applyColor(scheme: .cool) // シーン全体の雰囲気
raincloud.play(.soundscapeLoop, loops: true) // BGM
raincloud.animate(.rain) // 雨雲から雨が降る
raincloud.run(action: .scaleTo(3, duration: 5)) // 雨雲が大きくなる
}
シーンに追加したモデルごとに様々な挙動を指定できるので、いろいろ試してみると面白そうです。
どのモデルにも、play(_:loops:)
メソッド、animate()
メソッド、`run(action:)メソッドがあるようです。
これらを駆使すれば、独創的なシーンを構築できるはずです。
カメラのイベント
シーンにインタラクティブな効果をもたらします。
ここでは、ユーザーがiPadを持って3Dモデルに接近した時、アクションを行っています。
iPadのカメラとサボテンの距離が8cm以内になると、アクションが実行されます。
scene.camera.when(cactus, isWithin: 8.cm) {
scene.applyColor(scheme: .hot)
raincloud.remove()
label.text = "晴れの日! (^_^)"
let sun = Model.sun
scene.place(sun, at: cactus.location)
sun.run(group: [.moveBy(x: 0, y: 20.cm, z: 0, duration: 5),
.scaleBy(5, duration: 10)])
sun.animate()
}
イベントは、シーンにおけるカメラの場所からトリガーされます。
camera
オブジェクトのwhen(_:isWithin:do:)
メソッドによって実装されており、最後のパラメータはクロージャです。
ここでは、後付けクロージャ形式で記述されています。
クロージャでは、remove()
メソッドとplace(_:at:)
メソッドによって、雨雲モデルから太陽モデルへの変化を実装しています。
また、run(group:)
メソッドによって、太陽が上昇しつつ、大きくなる演出も行われています。
パラメータに、動作のコレクションを渡すことで、アクションを同時に実行できるようです。
ここでは、removeBy(x:y:z:duration:)
メソッドとscaleBy(_:duration:)
メソッドが列挙されています。
コードを読んでわかったこと
- 3Dモデルの作成は、イニシャライザを使っていない
- テキストの3Dモデルは、
text(_:elevation)
メソッド - シーンに複数のモデルを配置したい場合は、
add()
メソッドにモデルの配列を渡す - カメラによるイベントをハンドリングできる
-
run(group:)
メソッドで、複数のアクションを同時に実行できる
さらに...
このブックの次のページ「APIの概要」はこちらで解説します。