0

我和我的朋友正在实现一个基于一些开源谷歌项目代码 accelerometerplay 的弹珠游戏。我们的目的是制作一个玩具程序来自学安卓开发。我们正在经历以下情况:

问题:

弹珠在屏幕上滚动的速度极慢。这就像看着某物以慢动作移动。太糟糕了。我们怎样才能让它更快/正常播放?

我们所做的:

  1. 我们强制输入加速度计播放我们的代码,该代码从图块中绘制地图。虽然这会减慢速度。它仍然运行得很好。

  2. 我们重写了我们的视图以更接近原始的加速度计播放,并且仍然存在完全相同的问题,即我们的弹珠运行太慢,因此这消除了对我们不同类方法和简化的怀疑。

  3. 搜索了这个论坛。我们看到一些事情说 invalidate() 会使事情变慢,但我们不认为这是问题所在。它不应该杀死 onDraw() 来绘制一个弹珠以仅在屏幕上移动。

我们在下面包含我们的代码,用于程序的视图部分。其他类如活动或物理代码正在工作。我们 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 平板电脑,我相信是 10.1。如果有人能看出是什么导致我们的大理石移动缓慢,请告诉我们。我们在 onDraw 方法中做些什么吗?所有的阅读,包括指南,似乎都表明这应该有效,但我们似乎无法理解为什么我们的大理石移动如此缓慢。

感谢您的考虑,GeekyOmega

编辑:

读者想看 updatePositions(),改编自 google 开源示例,所以这里是:

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
4

1 回答 1

1

我认为您的问题与您的 FPS 设置有关。我在您的代码中没有看到它。
如果您不考虑 FPS 和当前帧速率,那么当 cpu 的负载变重时,事情会慢慢移动。
我记得遇到过类似的问题并完成了本教程,之后一切顺利。
如果您有时间,请尝试通过它。
希望这可以帮助。

于 2012-11-28T01:09:47.747 回答