Больше ничего не остается, кроме как согласиться с разумными аргументами, выдвинутыми во всех замечательных ответах выше, однако, если вы такой же прагматичный тип, как я, мне нужно найти решение, которое каким-то образом работает.
У меня возникла проблема, похожая на вашу, и я решил найти собственное решение, не найдя в сети. Для управления игрой мне понадобился только простой входной сигнал «наклона», поэтому это решение, вероятно, НЕ подойдет для более сложных задач, однако я решил поделиться им в случае, если другие ищут что-то похожее.
ПРИМЕЧАНИЕ: Я вставил сюда весь свой код , и он может свободно использоваться для любых целей.
В основном, я делаю в своем коде поиск датчика акселерометра. Если не найдено, обратная связь наклона будет отключена. Если датчик акселерометра присутствует, я ищу датчик магнитного поля, и, если он присутствует, я получаю рекомендованный угол наклона, комбинируя данные акселерометра и магнитного поля.
public TiltSensor(Context c) {
man = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
mag_sensor = man.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
acc_sensor = man.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
has_mag = man.registerListener(this, mag_sensor, delay);
has_acc = man.registerListener(this, acc_sensor, delay);
if (has_acc) {
tiltAvailble = true;
if (has_mag) {
Log.d("TiltCalc", "Using accelerometer + compass.");
}
else {
Log.d("TiltCalc", "Using only accelerometer.");
}
}
else {
tiltAvailble = false;
Log.d("TiltCalc", "No acceptable hardware found, tilt not available.");
//No use in having listeners registered
pause();
}
}
Если, однако, присутствовал только датчик акселерометра, я возвращаюсь к накоплению ускорения, которое постоянно уменьшается (умножается на 0,99), чтобы устранить любой дрейф. Для моих простых потребностей наклона это прекрасно работает.
@Override
public void onSensorChanged(SensorEvent e) {
final float[] vals = e.values;
final int type = e.sensor.getType();
switch (type) {
case (Sensor.TYPE_ACCELEROMETER): {
needsRecalc = true;
if (!has_mag) {
System.arraycopy(accelerometer, 0, old_acc, 0, 3);
}
System.arraycopy(vals, 0, accelerometer, 0, 3);
if (!has_mag) {
for (int i = 0; i < 3; i++) {
//Accumulate changes
final float sensitivity = 0.08f;
dampened_acc[i] += (accelerometer[i] - old_acc[i]) * sensitivity;
//Even out drift over time
dampened_acc[i] *= 0.99;
}
}
}
break;
case (Sensor.TYPE_MAGNETIC_FIELD): {
needsRecalc = true;
System.arraycopy(vals, 0, magnetic_field, 0, 3);
}
break;
}
}
В заключение я просто повторю, что это, вероятно, не «правильно», а просто работает как простой вход в игру. Чтобы использовать этот код, я просто делаю что-то вроде следующего (да, магические константы плохие, mkay):
Ship ship = mShipLayer.getShip();
mTiltSensor.getTilt(vals);
float deltaY = -vals[1] * 2;//1 is the index of the axis we are after
float offset = ((deltaY - (deltaY / 1.5f)));
if (null != ship) {
ship.setOffset(offset);
}
Enjoi!