Swift Playgroundsで学ぶiOSプログラミング

iPadの加速度センサーを使ってボールを動かすプログラミング

文●柴田文彦 編集●吉田ヒロ

2017年07月31日 17時00分

加速度計のデータを読み込んで重力としてセットする

 一般的にモーションマネージャを使って加速度計やジャイロスコープのデータを読み込む場合、あらかじめ計測のインターバルを設定したり、そのインターバルごとに呼ばれるファンクションを用意して、定期的にデータを処理する必要があります。

 ところがSpriteKitのシーンと一緒にモーションマネージャを利用する場合には、そうした設定や特別なファンクションの用意は不要になります。シーンには、アニメーション画面が更新される1フレームごとに呼ばれるupdateというメソッドがあります。これは通常は、ゲームを展開するためのロジックや、得点を計算して表示するといったプログラムを記述する場所です。しかし、モーションマネージャの加速度センサーなどの値を読み込んで処理するのにも最適な機会となります。

 そこでは、モーションマネージャから読み込んだ加速度の値をシーンの物理世界(physicsWorld)の加速度のプロパティにコピーするだけです。その際に、デバイスのy軸方向の加速度をシーンのx軸方向に、デバイスのx軸方向の加速度をシーンのy軸方向にセットしています。

シーンのupdateメソッドは、そのシーンのアニメーションの1フレームごとに呼ばれます。そのタイミングで加速度計の値を読み込み、縦と横を入れ替え、適当な係数をかけてからphysicsWorldのgravityにセットしています

 これは、このプレイグラウンドが、iPadを横向き(ランドスケープ)に持って見ることを前提としているからです。また、同時にシーンのx軸方向には-9.8、y軸方向には9.8の係数を掛けています。これはモーションマネージャの加速度計の値の単位がG(ジー)だからです。1Gは、地球の重力加速度に合わせた単位なので、約9.8m/s2になっているのはよく知られていますね。

画面を傾けてボールを動かす

 今回のプログラムは、前回の最後に示したものよりも、むしろ単純になっています。画面へのタッチを検出するtouchBeganメソッドの中で、タッチした位置にボールがあるかどうかを調べ、もしあれば、そのボールにランダムに縦横方向と回転方向の力を加えるという処理を省きました。つまりユーザーが画面にタッチしたら、その位置にボールを置くだけです。

 ボールが下まで落ちてしまったら、ゆっくりとiPad本体を動かして、画面を左右どちらかに傾けてみてください。その方向にボールが転がっていくはずです。

ボールが画面の下に落ちてしまったら、iPadを左右に傾けてみましょう。ボールは下になった方向に転がりながら移動するはずです

 iPad本体を画面が水平になるようにすると、シーンの重力がほとんどなくなり、ボールは浮遊状態になります。

iPadの画面が水平近くになると、だんだん重力が弱まります。完全に水平では重力がゼロになって浮遊状態になります

 この状態から少し反対側に傾けると、ボールは上に向かって移動していくでしょう。ただし、あまり傾けすぎると、iPadの画面全体が回転して、画面の向きだけでなく、重力の方向も反転したような状態になってしまうかもしれません。

 一般のiOSアプリであれば、プログラムによって画面の回転を禁止することができます。しかし、Swift Playgroundsの中のプレイグラウンドで動いているプログラムからは、Swift Playgroundsの画面の回転を禁止することはできません。あちこち画面を傾けてこのプログラムを楽しむには、「設定」の「一般」の「本体横のスイッチの機能」を「画面の向きをロック」に設定し、スイッチをオンにするのがいいでしょう。

障害物を置いて、ボールの動きに変化を付ける

 これまでは、シーンの中にはボールしか置いていませんでした。それでも複数のボールを出せば、ボール同士の衝突によって、それなりの動きの変化を確かめることはできました。それだけではシーンとしては寂しいので、何か障害物を置いてみましょう。もっとも簡単なのは、なんらかの画像から長方形のスプライトノードを作って置くことです。

 そのために、ここでは「woodBar.png」という横棒のような画像を用意して、それを画面の真ん中に置くことにします。その際のポイントは2つあります。1つは、その横長の長方形の画像の輪郭から物理体を作って設定しておくことです。そうしないとボールは素通りしてしまい、動きに変化はつきません。そのためには、前回と同様、SKPhysicsBodyクラスのオブジェクトを作る際にrectangleOfの引数ラベルを使って、画像の長方形のフレームサイズをそのまま物理体の輪郭に設定します。

 もう1つは、その物理体が重力やボールの衝突によって動かないようにシーンに固定しておくことです。それは物理体のisDynamicプロパティをfalseに設定するだけです。

物理体(ここでは画面中央に配置した横棒)のisDynamicプロパティをfalseに設定すると、重力で落ちることもなく、ほかの物体が衝突しても移動してしまうことがありません

 あとは、addChildメソッドによって、この横棒の画像から作ったノードを、シーンに貼り付けるのを忘れないようにするだけです。これだけで、シーンの中央に木製風のバーが表示され、それに衝突したボールが弾んだり、その上を転がったりするようになります。

画面の中央に配置した横棒は、物理体の輪郭として画像のフレームが設定してあるので、画像の輪郭に沿ってボールが転がったり、その境界で弾んだりします

ボールを置く際に力を加えて動きに変化を付ける

 余力のある人は、このプログラムにもうひと工夫加えてみましょう。例えば、touchBeganメソッドの中でボールを配置する際に、最初からボールに縦横方向、回転方向の力をランダムに加えてみるのはどうでしょうか。その方法は、前回にボールにタッチした際に力を加えるようにした処理と同じです。

前回のプログラムでは、ボールにタッチした際に加えていたランダムな力と回転力を、今回はボールを最初に配置する際に加えるようにしてみました。これだけでも動きに変化がつきます

 これによって、ボールの動きにはさらに変化が付きます。もちろん、すでに配置したボールにさらに力を加えるようにすることも難しくないでしょう。

 これまでのプログラムでは、物理体に設定したパラメータは、ほとんど実際の物理現象をシミュレートするような範囲のものでした。現実にはあり得ないようなパラメータを設定し、ボールがどのような動きを示すのか観察してみるのも面白いかもしれません。

次回の予定

 今回は、SpriteKitとCoreMotionを組み合わせて、よりリアルな物理シミュレーションを実現してみました。実はSpriteKitのノードには、あらかじめ形の決まった固定的なラベルやスプライトのノードだけでなく、よりダイナミックなエミッターノードというものもあります。いわゆるパーティクル・エミッターを実現するものです。次回は、そのあたりに挑戦してみるつもりです。

■今回作ったプログラム

Swift_49-1
Swift_49-2
Swift_49-3

mobileASCII.jp TOPページへ

mobile ASCII

Access Rankingアクセスランキング