3
\$\begingroup\$

Take Doodle Jump and other games that rely on the accelerometer. The movement of the character is very smooth and I have no idea how they implemented it. I've seen a number of SO/GameDev/forum questions, but the discussion ends abruptly when someone recommends a high/low pass filter. I've tried that (unless I'm missing something) and the results are nowhere near smooth.

All I'm trying to do is move a character on the x axis. This is the code I have and it's very "choppy". It's actually the code you can see on the official Android tutorials.

float alpha = 0.9f; //tried many values from 0.1f to 0.99f. chopiness still there @Override public void onSensorChanged(SensorEvent event) { if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { if(init) { gravity[0] = event.values[0]; gravity[1] = event.values[1]; gravity[2] = event.values[2]; init = false; } else { gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; } // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0]; linear_acceleration[1] = event.values[1] - gravity[1]; linear_acceleration[2] = event.values[2] - gravity[2]; character.setX(character.getX() - linear_acceleration[0]); } 

I also tried multiplying linear_acceleration[0] with a sensitivity, where 0 < sensitivity < 1 but the choppiness still doesn't go away. What is the next step from here to achieve a smooth movement like in Doodle Jump?

\$\endgroup\$
2
  • \$\begingroup\$ It's not "high/low pass filters" that remove choppiness. It's low pass filters specifically. What you have is a high pass filter, which does not remove choppiness. \$\endgroup\$ Commented Apr 8, 2014 at 0:34
  • \$\begingroup\$ @congusbongus I'm implementing this now: stackoverflow.com/a/5780505/1991295 Still absolutely no difference. \$\endgroup\$ Commented Apr 8, 2014 at 17:04

1 Answer 1

1
\$\begingroup\$

OK, I managed to sort this out and it was a bit stupid. Yes, the low-pass filter DOES solve the problem. Actually here's my code (note I'm doing it in a different method, but just copy and paste the contents in onSensorChanged(SensorEvent) if you wish:

private static final float alpha = 0.65f; private static final float SENSITIVITY = 1f/128; private boolean firstTime = true; @Override public void handleSensorEvent(SensorEvent event) { if(firstTime) { vals[0] = event.values[0]; vals[1] = event.values[1]; vals[2] = event.values[2]; } vals[0] = vals[0] + alpha * (event.values[0] - vals[0]); vals[1] = vals[1] + alpha * (event.values[1] - vals[1]); vals[2] = vals[2] + alpha * (event.values[2] - vals[2]); character.setX( character.getX() - vals[0] * SENSITIVITY ); } 

You can calibrate alpha and SENSITIVITY according to your needs. Now this is why this code was producing very choppy movement initially: in my activity's onResume() I was registering my listener using SensorEvent.SENSOR_DELAY_NORMAL. That is wrong. What you have to do is register it with SensorEvent.SENSOR_DELAY_GAME. I think the reason behind this is obvious. So in your activity's onResume():

sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME); 

where accelerometer is declared as (in onCreate()):

accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.