I'm trying to develop an app where the user can hit an invisible drum using the motion of the phone. So that when the phone is flicked downwards a drum is sounded at the end of the flick.
I have managed to get 90% of this working, by detecting when a large, quick movement suddenly stops. But although the drum is being sounded after a flick (good) it's also being sounded at the end of a pull (not desirable).
By flick I mean the phone is being flicked forwards and downwards, as if you are striking a drum with it, and by pull I mean you are returning your arm back to the starting position.
Does anyone know an efficient way of determining when a flick occurs but not a push?
Any ideas will be gratefully received.
Thanks
EXISTING CODE:
package com.example.testaccelerometer;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity implements SensorEventListener{
public static TextView results;
public static TextView clickresults;
StringBuilder builder = new StringBuilder();
private float mAccelNoGrav;
private float mAccelWithGrav;
private float mLastAccelWithGrav;
public static boolean shakeIsHappening;
public static int beatnumber = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
results = (TextView) findViewById(R.id.results);
clickresults = (TextView) findViewById(R.id.clickresults);
SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if(!manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST)){
builder.append("Problem with Accelerometer - Shaking will not work");
};
mAccelNoGrav = 0.00f;
mAccelWithGrav = SensorManager.GRAVITY_EARTH;
mLastAccelWithGrav = SensorManager.GRAVITY_EARTH;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent event) {
builder.setLength(0);
builder.append("X " + event.values[0] + "\nY " + event.values[1] + "\nZ " + event.values[2]);
results.setText(builder.toString());
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
mLastAccelWithGrav = mAccelWithGrav;
mAccelWithGrav = android.util.FloatMath.sqrt(x*x + y*y + z*z);
float delta = mAccelWithGrav - mLastAccelWithGrav;
mAccelNoGrav = mAccelNoGrav * 0.9f + delta;
if (mAccelNoGrav >8.5) {
shakeIsHappening = true;
//clickresults.append(" click " + mAccel);
}
if (shakeIsHappening == true && mAccelNoGrav <2) {
beatnumber++;
clickresults.append(" click number: " + beatnumber + "\n" + "PA: " + mLastAccelWithGrav + " CA:" + mAccelNoGrav + "\n ");
shakeIsHappening = false;
}
}
@Override
protected void onResume() {
super.onResume();
// YOU DO NEED TO TRY AND REREGISTER IT NOW
}
@Override
protected void onPause() {
// YOU DO NEED TO TRY AND UNREGISTER IT NOW
super.onPause();
}
}