シェイクイベントを取得して、コマの配列のシャッフルを実行するようにします。
加速度センサーとか、使うみたいです。未知の領域です。。できるんでしょうか…。
やってみます。
センサーのイベントを取れるようにする
Androidでは、SensorEventListener を実装するコトでセンサーのイベントが取れる様になります。”イベントリスナーを実装する”っていい方になるようです。
public class MainActivity extends ActionBarActivity implements SensorEventListener {
// ゲームビューのインスタンス
private GameView gameView;
// センサーマネージャ
private SensorManager mSensorManager;
// シェイク判定用のメンバー変数
private float beforeX;
private float beforeY;
private float beforeZ;
private long beforeTime = -1; // 前回の時間
private float shakeSpeed = 80; // 振ってると判断するスピード
private float shakeCount = 0; // 振ってると判断した回数
これで、イベントが取れるようになります。実装に必要なメンバー変数を追加しています。
SensorManager がセンサーのオブジェクトを操作するオブジェクト、肝心なやつですね。これは後で onCreate でインスタンスを作っていきます。
SensorEventListener を指定することで、センサーのイベントが取れる様になります。今回は onSensorChanged を使ってシェイクしているかを判断していきます。
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy){
// 未使用
}
@Override
public void onSensorChanged(SensorEvent event){
// 色々実装していきます。
その前に、センサーオブジェクトの準備をしておきます。
センサーを登録する
まず、センサーマネージャを生成します。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ゲームビューのインスタンス作成
gameView = new GameView(this);
// センサーマネージャのインスタンス作成
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// ツールバーを非表示
requestWindowFeature(Window.FEATURE_NO_TITLE);
// ゲームビューを表示
setContentView(gameView);
}
onCreate で生成していきます。シェイクした時に、GameView のシャッフル関数と再描画を呼び出したかったので、GameView のインスタンスをメンバで持つように変えています。
で、onResume で、センサーオブジェクトを登録する、ってことをやります。
@Override
protected void onResume(){
super.onResume();
// 加速度センサーのオブジェクト取得
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
// センサーを登録
if(sensors.size() > 0){
Sensor s = sensors.get(0);
mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_UI);
}
// 初期化
beforeX = 0;
beforeY = 0;
beforeZ = 0;
beforeTime = -1;
}
mSensorManager.registerListener の部分ですね。登録しないと、イベント取れないみたいです。
で、イベントを取りっぱなしにしていると、アプリが裏に行っても電池食うみたいです。恐ろしい!!!
なので、 onPause で、センサーの登録を解除しておきます。
@Override
protected void onPause() {
super.onPause();
// センサーの登録を解除
if(mSensorManager != null)
mSensorManager.unregisterListener(this);
}
mSensorManager.unregisterListener で解除できるそうです。
で、onResume / onPause については、下のページが大変参考になりました。
http://www.javadrive.jp/android/activity/index2.html
こちらのページには、事あるごとにお世話になっている気がします…。いつもありがとうございます。
で、いよいよ onSensorChanged の実装です。
@Override
public void onSensorChanged(SensorEvent event){
switch(event.sensor.getType()){
// 加速度センサーのイベントをハンドリング
case Sensor.TYPE_ACCELEROMETER:
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
long nowTime = System.currentTimeMillis();
// 最初のイベント→値を保持するのみ
if( beforeTime == -1 ){
beforeX = x;
beforeY = y;
beforeZ = z;
beforeTime = nowTime;
break;
}
// 0.5秒間隔でチェック
long diffTime = nowTime - beforeTime;
if( diffTime < 500 )
break;
// 前回の値との差から、スピードを算出
// すみません、どうしてこれでOKなのか、不勉強でまだ理解出来ていません。。。
float speed = Math.abs(x + y + z - beforeX - beforeY - beforeZ) / diffTime * 10000;
// スピードがしきい値以上の場合、振ってるとみなす
if( speed > shakeSpeed ){
// 振ってると判断した回数が3以上、つまり1.5秒間振り続けたら、シャッフルする
if(++shakeCount > 2){
shakeCount = 0;
// コマの並びをシャッフルし、再描画
gameView.shufflePieces();
gameView.invalidate();
}
}
else {
// 途中でフリが収まった場合は、カウントを初期化
shakeCount = 0;
}
// 前回の値を覚える
beforeX = x;
beforeY = y;
beforeZ = z;
beforeTime = nowTime;
break;
}
}
こんな感じです。特定の加速度が1.5秒以上キープされたらシャッフルする様にしています。
ホントは3回振ったら、とか思って実装していたのですが、勘違いでした。加速度の判断の部分がまだ不勉強で理解出来ていないのですが…、だいたい満足な動作をしています。
とりあえず振ってシャッフル、できました!!!
ただ、端末によって取れる加速度の値が大分異なるようなので…、3回タップでシャッフルってのも入れておこうかな。。
ソースコードはこちらで公開しています。
https://github.com/et79/Game15