为什么我们的安卓游戏,特别是我们的大理石,移动得如此之慢?

时间:2012-11-27 23:49:04

标签: android performance debugging ondraw

我的朋友和我正在实施基于一些开源谷歌项目代码,accelerometerplay的大理石游戏。我们的目的是制作一个玩具程序来教我们自己的android开发。我们正在经历以下情况:

问题:

大理石在屏幕上滚动的速度非常慢。这就像看着慢动作的东西移动。太糟糕了。我们怎样才能让它更快/更正常?

我们做了什么:

  1. 我们强制使用fedrometerplay我们的代码从瓷砖绘制地图。虽然这会减慢速度。它仍然运行良好。

  2. 我们改写了我们的视图以匹配原来的加速度计更接近,并且仍然存在与我们的大理石运行速度太慢的完全相同的问题,因此这消除了对我们的不同类方法和简化的怀疑。

  3. 搜索此论坛。我们看到一些事情说invalidate()使事情变慢,但我们不相信这是问题。它不应该杀死onDraw()来绘制一个大理石只在屏幕上移动。

  4. 我们将以下代码包含在程序的视图部分中。其他类如活动或物理代码正在运行。我们100%确定这个问题正在这个类中发生,它正在试图绘制大理石来移动。

    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) {
    }
    
    }
    

    我们撞到了一堵砖墙,以减缓我们大理石的速度。我相信,我们正在使用三星Galaxy平板电脑。如果有人能看到导致我们的大理石缓慢移动的原因,请告诉我们。我们在onDraw方法中做了什么吗?所有的阅读,包括指南,似乎表明这应该有效,但我们似乎无法理解为什么我们的大理石移动如此缓慢。

    感谢您的考虑, GeekyOmega

    编辑:

    读者希望看到updatePositions(),改编自谷歌开源示例,所以你在这里:

    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
    

1 个答案:

答案 0 :(得分:1)

我认为您的问题与您的FPS设置有关。我的代码中没有看到它 如果不考虑FPS和当前帧速率,当cpu的负载变重时,事物将缓慢移动。
我记得有过类似的问题并经历了这个tutorial之后,一切都顺利了。
如果你有时间尝试通过它。
希望这会有所帮助。