GeekyOmega
GeekyOmega

Reputation: 1305

Why is our android game, specifically our marble, moving around so slow?

My friend and I are implementing a marble game based on some open source google project code, accelerometerplay. Our purpose is to make a toy program to teach ourselves android development. We are experiencing the following:

Problem:

The marble will roll on the screen extremely slow. It is like watching something move around in slow motion. It is awful. How can we make it faster/normal play?

What we have done:

  1. We force fed accelerometerplay our code which draws a map from tiles. While this slows things down. It still runs pretty good.

  2. We rewrote our view to match the original accelerometerplay closer, and still have the exact same problem that our marble is running too slow, so this removes doubt about our different class approach and simplification.

  3. Searched this forum. We saw some things saying that invalidate() makes things slow, but we don't believe that is the problem. It shouldn't kill onDraw() to draw one marble to move around on the screen only.

We include our code below for our view portion of the program. The other classes like activity, or physics code is working. We are 100% sure that the problem is happening in this class where it is trying to draw the marble to move around.

package com.example.marblez;
import com.example.marblez.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;


import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;

public class MarblezView extends View implements SensorEventListener{


//Sensor Stuff
private SensorManager mSensorManager;
private Display mDisplay;


//Accelerometer sensor stuff 
private Sensor mAccelerometer;
private float mSensorX;
private float mSensorY;


//Variables related to time 
private long mCpuTimeStamp;
private long mSensorTimeStamp;
private WindowManager mWindowManager;


//Create the canvas 
private Canvas mCanvas; 
private MarblezBackground background;

//Create the ball objects
private Bitmap mBall;
private Bitmap ball;

//Finally call marblez system 
private final MarblezSystem mMarblezSystem = new MarblezSystem();


//Constructor for Marblez View 
@SuppressWarnings("deprecation")
public MarblezView(Context context, Activity activity){
    super(context);

    //Setup sensor stuff
    mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);

    mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    mDisplay = mWindowManager.getDefaultDisplay();



    //Set up Maze 
    background = new MarblezBackground(activity);

    //Create our rolling little friend :-) 
    Options opts = new Options();
    opts.inDither = true;
    opts.inPreferredConfig = Bitmap.Config.RGB_565;

    mBall = BitmapFactory.decodeResource(activity.getApplicationContext().getResources(), R.drawable.ball, opts);

    // Rescale the ball to be whatever size you wish it to be
    final int dstWidth = (int) 30;//(sBallDiameter * mMetersToPixelsX + 0.5f);
    final int dstHeight = (int) 30;//(sBallDiameter * mMetersToPixelsY + 0.5f);
    ball = Bitmap.createScaledBitmap(mBall, dstWidth, dstHeight, true);

}

 @Override
 public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
         return;
     /*
      * record the accelerometer data, the event's timestamp as well as
      * the current time. The latter is needed so we can calculate the
      * "present" time during rendering. In this application, we need to
      * take into account how the screen is rotated with respect to the
      * sensors (which always return data in a coordinate space aligned
      * to with the screen in its native orientation).
      */
     mSensorX =  event.values[0];
     mSensorY = -event.values[1];


     mSensorTimeStamp = event.timestamp;
     mCpuTimeStamp = System.nanoTime();
 }


//Automatic call
@Override
public void onDraw(Canvas canvas){
    //mCanvas = canvas;

    //Draw the maze
    //background.drawMaze(canvas);


    //Update the position and then draw the marble 
    final MarblezSystem marblezSystem = mMarblezSystem;
    final long now = mSensorTimeStamp + (System.nanoTime() - mCpuTimeStamp);
    final float sx = mSensorX;
    final float sy = mSensorY;

    marblezSystem.updatePositions(sx, sy, now);
    final float x = marblezSystem.getPosX();
    final float y = marblezSystem.getPosY();
    canvas.drawBitmap(ball, x, y, null);

    //Invalidate so it draws again 
    invalidate();

}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

}

We have hit a brick wall at to what is slowing down our marble. We are using a Samsung Galaxy tablet, 10.1 I believe. If anyone can see what is causing our marble to move slowly, please let us know. Are we doing something in the onDraw method? All the reading, guides included, seem to indicates that this should work, but we can't seem to understand why our marble is moving so slow.

Thank you for your consideration, GeekyOmega

EDIT:

Readers wanted to see the updatePositions(), is adapted from google open source example, so here you are:

package com.example.marblez;

public class MarblezSystem {

  private long mLastT;
  private float mLastDeltaT;
  private Marblez ball;

  MarblezSystem() {
      /*
       * Initially our marble have no speed or acceleration
       */
          ball = new Marblez();
      }


  /*
   * Update the position of marble in the system using the
   * Verlet integrator.
   */
  public void updatePositions(float sx, float sy, long timestamp) {
      final long t = timestamp;
      if (mLastT != 0) {
          final float dT = (float) (t - mLastT) * (1.0f / 1000000000.0f);
          if (mLastDeltaT != 0) {
              final float dTC = dT / mLastDeltaT;
                  //Particle ball = mBalls[i];
                  ball.computePhysics(sx, sy, dT, dTC);

          }
          mLastDeltaT = dT;
      }
      mLastT = t;
  }


  public float getPosX() {
      return ball.mPosX;
  }

  public float getPosY() {
      return ball.mPosY;
  }

}//End of MarblezSystem

Upvotes: 0

Views: 650

Answers (1)

Lazy Ninja
Lazy Ninja

Reputation: 22537

I think your problem has something to do with your FPS setting. I don't see it in your code.
If you don't take the FPS and the current frame rate in consideration things will move around slowly when the cpu's load become heavy.
I remember having similar problem and went through this tutorial and after that everything went smooth.
If you have time try to go through it.
Hope this helps.

Upvotes: 1

Related Questions