Step3 モーションセンサー機能を使ってみよう
では実際にコードを書いてアプリをつくろうと思いますが、ただセンサーの情報に合わせて数値が変化するだけのようなアプリではツマらないですし飽きてしまうと思うので、Step2で学習した内容を使ってせっかくなので実際に簡単な「玉転がしゲーム」を作ってみたいと思います。
ですので、少々ゲームプログラミングの知識等が必要になってしまいますが、以降で解説もしますのでコードを参考にしながら一緒に頑張りましょう!
<端末の縦方向の傾き:Pitch>
水平時 : 0度
上に傾ける : 0〜-180度
下に傾ける : 0〜180度
<端末の横方向の傾き:Roll>
水平時 : 0度
左に傾ける : 0〜90度
右に傾ける : 0〜-90度
[1]傾きセンサーから傾きの情報を取得する
傾きの情報を取得するのは、SensorManagerのインスタンスを取得して、イベントハンドラを登録するだけなので簡単です。
アプリの初期化タイミングでは、以下のようなコードを書きます。
private void initialize(Context context) { // 傾きを初期化 Pitch = 0; Roll = 0; // SensorManagerを取得 SensorManager = (SensorManager)context.getSystemService( Context.SENSOR_SERVICE); // イベントハンドラを登録 SensorManager.registerListener( new SensorEventListener() { @Override public void onAccuracyChanged( Sensor sensor, int accuracy) { } @Override public void onSensorChanged( SensorEvent event) { // 傾きを更新 Pitch = event.values[SensorManager.DATA_Y]; Roll = event.values[SensorManager.DATA_Z]; } }, SensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME); } |
onSensorChanged()がイベントハンドラです。ここでは傾きの値をメンバ変数に記録しています。傾きの値をボールに反映させるのは別の箇所で行います。
SensorManager.registerListener()の第2引数は傾きセンサーを表します。第3引数はセンサーの反応速度です。SensorManager.SENSOR_DELAY_GAMEは20ms間隔で、かなり速い反応速度です。
[2]傾きをボールに伝える
ボールはスレッドで動かします。スレッドで実行するrun()メソッドの中で、傾き(Pitch、Roll)をボールに伝えます。
public void run() { (省略) while (Thread != null) { // 0.01秒のwaitを入れる try { Thread.sleep(10); } catch (InterruptedException e) { } try { (省略) // ボールを移動・描画 Ball.move(Pitch, Roll); Ball.draw(canvas); } } finally { (省略) } } } |
[4]玉を移動する
Ball.move()メソッドで玉を移動させます。以下にコードの抜粋を示します。
// 加速量 private final double Acceleration = 1.5; // 減衰量 private final double Attenuator = 0.02; // 壁のはね返り量 private final double Bound = 0.5; public void move(float Pitch, float Roll) { // 傾きから移動量の変動幅を計算 double dx = - Math.sin(Math.toRadians(Roll)) * Acceleration; double dy = - Math.sin(Math.toRadians(Pitch)) * Acceleration; // 傾きによって移動量を修正 Dx += Dx * -mAttenuator + dx; Dy += Dy * -mAttenuator + dy; // ボールを移動 Rect.offset((int)Dx, (int)Dy); // 表示範囲の枠に当たったらはね返す (省略) } |
Ball.move()メソッドの先頭では、傾きの大きさに応じて移動が加速するように、 三角関数を使って加速量(dx、dy)を計算しています。
次に、現在の移動速度(Dx、Dy)を少し減衰させた上で、加速量(dx、dy)を足しています。減衰をしないと玉の勢いがありすぎてコントロールしにくいと感じましたので、今回はこのようにしています。
また上述では省略していますが、壁に当たると跳ね返るようにしています。このとき、ブロック崩しのように同じ速度で跳ね返ると不自然に感じましたので、跳ね返った時の移動速度を減衰させるようにしています。
現実世界でも摩擦により玉の移動速度に減衰が生じたり、壁に当たった玉が跳ね返る瞬間に、壁やボールがその衝撃を吸収していることと同じですね。
こうした、加速量・減衰量・はね返り量といったものを微妙に調整することで、玉のコントロールの難易度や自然さが決まっていくようです。今回は実装していませんが、動摩擦係数 < 静摩擦係数とすることで、静止状態からの玉の動き出しがより自然になると思います。
このように、端末を傾けるとそれぞれの方向に、玉が移動します。
いかがでしたでしょうか?
今回で、センサーの使い方がどんな感じなのか大まかに掴めたのではないでしょうか?
次回は、方位センサーについて今回同様実際にアプリを作りながら説明していきたいと思いますのでお楽しみに。
今回コラムで使用したプログラムはこちらからダウンロード出来ます。
第7回 センサーを使ってみよう(前編)
Step1 Android™ のセンサー機能
Step2 センサーの使い方
Step3 モーションセンサー機能を使ってみよう
(文責:株式会社ベストクリエイト)
■免責事項