ユーザーID パスワード

技術情報

  • FAQ よくある質問
  • 個人ユーザー向けサービスのお手続きについて

コード&コラム

第7回
センサーを使ってみよう(前編)


前へ 1 |2 |3 |4

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)を足しています。減衰をしないと玉の勢いがありすぎてコントロールしにくいと感じましたので、今回はこのようにしています。
また上述では省略していますが、壁に当たると跳ね返るようにしています。このとき、ブロック崩しのように同じ速度で跳ね返ると不自然に感じましたので、跳ね返った時の移動速度を減衰させるようにしています。

現実世界でも摩擦により玉の移動速度に減衰が生じたり、壁に当たった玉が跳ね返る瞬間に、壁やボールがその衝撃を吸収していることと同じですね。

こうした、加速量・減衰量・はね返り量といったものを微妙に調整することで、玉のコントロールの難易度や自然さが決まっていくようです。今回は実装していませんが、動摩擦係数 < 静摩擦係数とすることで、静止状態からの玉の動き出しがより自然になると思います。

img

このように、端末を傾けるとそれぞれの方向に、玉が移動します。


いかがでしたでしょうか?
今回で、センサーの使い方がどんな感じなのか大まかに掴めたのではないでしょうか?
次回は、方位センサーについて今回同様実際にアプリを作りながら説明していきたいと思いますのでお楽しみに。


今回コラムで使用したプログラムはこちらからダウンロード出来ます。


第7回 センサーを使ってみよう(前編)
 Step1 Android™ のセンサー機能
 Step2 センサーの使い方
 Step3 モーションセンサー機能を使ってみよう

(文責:株式会社ベストクリエイト)

■免責事項

本コラム内で提供する情報のご利用は、利用者ご自身の責任において行われるものとします。本コラムで提供される各種情報については、慎重に作成、管理をしておりますが、当社は、これらの情報の正確性、有用性、完全性等を保証するものではありません。当社は、利用者がこれらの情報をご利用になったこと、またはご利用になれなかったことにより生じたいかなる損害についても責任を負いません。
本コラムで提供される各種情報に関し、利用者と他の利用者あるいは第三者と紛争が生じた場合、利用者は自己の費用と責任においてこれを解決するものとし、当社に損害を与えないものとします。
当社は、本コラムに掲載する情報の全部又は一部を予告なく変更する場合がございます。また、本コラムの運用を休止または停止する場合がございます。
当社は、理由の如何を問わず本コラムの提供が遅延し、または中断したことに起因して利用者または第三者が被った被害について、一切の責任を負いません。
当社は、利用者が、本コラムで提供している情報からリンクが張られている第三者のウェブサイト、または本サイトへリンクを張っている第三者のウェブサイトから取得された各種情報のご利用によって生じたいかなる損害についても責任を負いません。
通信環境、利用者のコンピューター環境その他の理由により、本コラムが正常にご利用できない場合がございます。
当社は、本コラムから入手された文書・写真・イラスト・動画・リンクその他各種情報(以下総称して「情報」といいます)に関して技術的サポート、機能改善等のいかなる技術的役務の提供もいたしかねますので、あらかじめご了承ください。
本掲載内容・各種名称は公開日時点のものであり、団体・サービス・ツール等の名称が変更されることがあります。

サンプルコード

第1回 リファレンスコード(文字列編)

第2回 リファレンスコード2(グラフィックス編)

第3回 リファレンスコード3(タッチイベント編)

第4回 リファレンスコード4(チェックボックス/ラジオグループ編)

第5回 リファレンスコード5(スピナー編)

第6回 リファレンスコード6(サウンド/ムービー編)

第7回 リファレンスコード7(トースト編)

第8回 リファレンスコード8(Google Maps API利用編)

第9回 リファレンスコード9(SQLite編)

第10回 リファレンスコード10(音声認識編)

第11回 リファレンスコード11(日付/時刻ダイアログ編)

第12回 リファレンスコード12(Bluetooth編)