5

i have done developed a sample application with the help of tutorials posted on web. my aim is to access the accelerometer and move a ball as per the phone orientation. i was successful to certail extent. But i have two isses

  1. the ball is going out of bound of the screen
  2. the ball movement is not smooth ( looks it disappears and re appears on the screen)

here is my code. is there any change i need to do to get the smooth and exact movement of the ball as we see in lot of games.

public class Accelerometer extends Activity implements SensorEventListener{
    /** Called when the activity is first created. */
    CustomDrawableView mCustomDrawableView = null;
    ShapeDrawable mDrawable = new ShapeDrawable();
    public static int x;
    public static int y;
       private Bitmap mBitmap;
       private Bitmap mWood;
    private SensorManager sensorManager = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        // Get a reference to a SensorManager
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mCustomDrawableView = new CustomDrawableView(this);
        setContentView(mCustomDrawableView);
        // setContentView(R.layout.main);

    }

    // This method will update the UI on new sensor events
    public void onSensorChanged(SensorEvent sensorEvent)
    {
        {
           /* if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                // the values you were calculating originally here were over 10000!
                x = (int) Math.pow(sensorEvent.values[0], 2); 
                y = (int) Math.pow(sensorEvent.values[1], 2);

            }*/

            if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
                  Display display = getWindowManager().getDefaultDisplay(); 
                  int xmax = display.getWidth();
                  int ymax = display.getHeight();
                  x = (int) Math.pow(sensorEvent.values[1], 2); 
                  y = (int) Math.pow(sensorEvent.values[2], 2);
                  if (x > xmax) {
                      x = xmax;
                  } else if (x < -xmax) {
                      x = -xmax;
                  }
                  if (y > ymax) { 
                      y = ymax;
                  } else if (y < -ymax) {
                      y = -ymax;
                  }

            }
        }
    }

    // I've chosen to not implement this method
    public void onAccuracyChanged(Sensor arg0, int arg1)
    {
        // TODO Auto-generated method stub

    }

    @Override
    protected void onResume()
    {
        super.onResume();
        // Register this class as a listener for the accelerometer sensor
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                SensorManager.SENSOR_DELAY_GAME);
        // ...and the orientation sensor
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                SensorManager.SENSOR_DELAY_NORMAL); 
    }

    @Override
    protected void onStop()
    {
        // Unregister the listener
        sensorManager.unregisterListener(this);
        super.onStop();
    }

    public class CustomDrawableView extends View
    {


        public CustomDrawableView(Context context)
        {
            super(context);

          Bitmap ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
          final int dstWidth = 50; 
          final int dstHeight = 50; 
          mBitmap = Bitmap.createScaledBitmap(ball, dstWidth, dstHeight, true);
          mWood = BitmapFactory.decodeResource(getResources(), R.drawable.wood);

        }

        protected void onDraw(Canvas canvas)
        {

            final Bitmap bitmap = mBitmap;

            canvas.drawBitmap(mWood, 0, 0, null);
            canvas.drawBitmap(bitmap, x, y, null);

            invalidate();
        }
    }
}
Cristian
  • 198,401
  • 62
  • 356
  • 264
sankara rao bhatta
  • 649
  • 5
  • 9
  • 13
  • .. perfect match to what you are looking for is [here](http://www.appsrox.com/android/tutorials/accelerometer-golf/) – user2230793 May 30 '14 at 18:52

2 Answers2

13

Is this not the same question as your last question here?! You should just edit/expand your original question rather that starting a new one!

But basically to make it realistic you want to move the ball by using x/y speed rather than just changing the position. So you want to have a loop which draws the ball and you want to know the time difference between the current loop and the previous, then you can use simple kinematics equations to work out the position change.

For example:

newspeed = oldSpeed + (acceleration * time)
distance = (original speed*time) + (0.5 * acceleration * time^2).

Where you use sensor inputs to set the acceleration, then just add the calculated distance to the balls position.


EDIT - Code as requested.

Your lucky you found a bored games programmer! It's not perfect by any means but its working for you. You should buy yourself a game development book and have a look at using open GL for this as it would be a lot better!

public class test2 extends Activity implements SensorEventListener{

CustomDrawableView mCustomDrawableView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public float xPosition, xAcceleration,xVelocity = 0.0f;
public float yPosition, yAcceleration,yVelocity = 0.0f;
public float xmax,ymax;
private Bitmap mBitmap;
private Bitmap mWood;
private SensorManager sensorManager = null;
public float frameTime = 0.666f;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);

    //Set FullScreen & portrait
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    // Get a reference to a SensorManager
    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME);

    mCustomDrawableView = new CustomDrawableView(this);
    setContentView(mCustomDrawableView);
    // setContentView(R.layout.main);

    //Calculate Boundry
    Display display = getWindowManager().getDefaultDisplay();
    xmax = (float)display.getWidth() - 50;
    ymax = (float)display.getHeight() - 50;
}

// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent)
{
    {
        if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
            //Set sensor values as acceleration
            yAcceleration = sensorEvent.values[1]; 
            xAcceleration = sensorEvent.values[2];
            updateBall();
        }
    }
}

private void updateBall() {


    //Calculate new speed
    xVelocity += (xAcceleration * frameTime);
    yVelocity += (yAcceleration * frameTime);

    //Calc distance travelled in that time
    float xS = (xVelocity/2)*frameTime;
    float yS = (yVelocity/2)*frameTime;

    //Add to position negative due to sensor 
    //readings being opposite to what we want!
    xPosition -= xS; 
    yPosition -= yS;

    if (xPosition > xmax) {
        xPosition = xmax;
    } else if (xPosition < 0) {
        xPosition = 0;
    }
    if (yPosition > ymax) { 
        yPosition = ymax;
    } else if (yPosition < 0) {
        yPosition = 0;
    }
}

// I've chosen to not implement this method
public void onAccuracyChanged(Sensor arg0, int arg1)
{
    // TODO Auto-generated method stub
}

@Override
protected void onResume()
{
    super.onResume();
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_GAME); 
}

@Override
protected void onStop()
{
    // Unregister the listener
    sensorManager.unregisterListener(this);
    super.onStop();
}

public class CustomDrawableView extends View
{
    public CustomDrawableView(Context context)
    {
        super(context);
        Bitmap ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
        final int dstWidth = 50; 
        final int dstHeight = 50; 
        mBitmap = Bitmap.createScaledBitmap(ball, dstWidth, dstHeight, true);
        mWood = BitmapFactory.decodeResource(getResources(), R.drawable.wood);

    }

    protected void onDraw(Canvas canvas)
    {
        final Bitmap bitmap = mBitmap;
        canvas.drawBitmap(mWood, 0, 0, null);
        canvas.drawBitmap(bitmap, xPosition, yPosition, null);
        invalidate();
    }
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    // TODO Auto-generated method stub
    super.onConfigurationChanged(newConfig);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
Community
  • 1
  • 1
Kenny
  • 5,522
  • 2
  • 18
  • 29
  • hey i am very much new to this site. i wanted close the earlier question but could not see the option anywhere. may be i am not looking at the right place. how do i accept the answer? – sankara rao bhatta Jun 25 '11 at 18:51
  • hi i got how to accept the answer. i have accepted your previous answer.thanks – sankara rao bhatta Jun 25 '11 at 19:04
  • hi kenny, sounds good. but i am new to java as well. can you change my code and put the logic explained by you – sankara rao bhatta Jun 25 '11 at 19:08
  • There you go, i've added it to the answer - your lucky i was bored and had nothing better to be doing! lol - enjoy. – Kenny Jun 25 '11 at 20:42
  • thanks kenny i will try the code given by you and also explore the open GL. – sankara rao bhatta Jun 26 '11 at 08:52
  • really good answer Kenny. I am implementing the same thing in OpenGL ES but have different classes set up for `Activity`, `Renderer` and `Particle` [Right Here](http://stackoverflow.com/questions/9879201/drawing-multiple-cubes-at-random-positions-in-opengl-es-android) Dont bother about the content coz it has changed a lot. My only concern is how can I get the movements of the particle updated inside the Activity class since the SensorManager methods are implemented inside activity and particles are drawn and positioned inside the Renderer class. – jmishra Mar 29 '12 at 09:28
  • Why xVelocity and yVelocity never change? are they supposed to be 0.0f all the time? – Rohit Malish Sep 02 '12 at 19:11
  • Hi @Kenny, I know this a really old question, but if you wouldn't mind, could you take a look at my question here: https://stackoverflow.com/questions/34839375/acclerometer-and-moving-object-left-right-android… I'm not sure I'm doing this right. Thanks – Zippy Jan 17 '16 at 14:22
  • @Kenny can you suggest Book name for learning Game programming in android , I know its off topic but I can really need your help – Sanjeev Jun 21 '16 at 15:45
2

I would set SENSOR_DELAY constant to

SENSOR_DELAY_FASTEST 

See if that fixes it. This should help the stutter problem. Also I think your boundary checks are wrong since xmax and ymax values are given display.getWidth/getHeight Maybe you should feed it your BitMap width and height boundaries to the xmax and ymax values.

BobMcboberson
  • 2,065
  • 2
  • 13
  • 13