1

在过去的几天里,我一直在玩传感器和画布。

到目前为止,我已经设法根据设备的角度控制位图的位置。

应用程序的工作方式是获取方向数据,并根据设备倾斜的程度,在屏幕上向左或向右移动位图。

我在运行 android 4.2.2 (AOKP) 的三星 Galaxy S II GT-i9100 上进行了大部分测试,该应用程序运行得非常完美,除了应用程序在恢复时崩溃(我想我知道是什么原因造成的)。

我遇到的问题如下:

当我尝试在 Sony Xperia Z(运行 android 4.1.2,Sony 的股票)上运行相同的代码时,整个应用程序变得不稳定(位图几乎不移动),我认为这是因为传感器数据检索不稳定/缓慢。我朋友的索尼 Xperia S 也是如此。

我把这个应用程序给了我的另一个拥有 Nexus 4 的朋友,他说他没有这样的问题。

游戏视图

public class GameView extends SurfaceView {

    private Bitmap bmp;
    private SurfaceHolder holder;
    private GameLoopThread gameLoopThread;
    private int x = 0;
    private int xMultiplier = 0;
    private Paint textPaint;

    //lowPass
    private float smoothVal = 0; //Main variable, check algorithm
    private int smoothing = 5; //How strong the smoothing is, larger the value, more time is needed before the value reaches actual sensor value



    //Sensors
    private SensorManager sensorManager;
    private SensorEventListener sensorEventListener;

    //Rotation matrices for converting coordinate systems
    private float[] rotationMatrixR = new float[9];
    private float[] rotationMatrixI = new float[9];

    //Arrays storing data for gravity and geomagnetic data needed to get device's angles
    private float[] gravity = new float[3];
    private float[] geomagnetic = new float[3];

    //Array holding angles
    private float[] angles = new float[3];




    public GameView(Context context) {
        super(context);
        gameLoopThread = new GameLoopThread(this);
        holder = getHolder();
        textPaint = new Paint();
        textPaint.setColor(Color.WHITE);
        textPaint.setTextSize(20);

        sensorManager = (SensorManager)getContext().getSystemService(Context.SENSOR_SERVICE);

        sensorEventListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent sensorEvent) {

                Sensor sensor = sensorEvent.sensor;

                if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                    gravity = sensorEvent.values;
                }
                else if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                    geomagnetic = sensorEvent.values;
                }

                SensorManager.getRotationMatrix(rotationMatrixR, rotationMatrixI, gravity, geomagnetic);
                SensorManager.getOrientation(rotationMatrixR, angles);
            }

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

            }
        };

        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
        sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_FASTEST);



        holder.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                boolean retry = true;
                gameLoopThread.setRunning(false);

                while (retry) {
                    try {
                        gameLoopThread.join();
                        retry = false;
                    }
                    catch (InterruptedException e) {
                        //Shit hit the fan
                        Log.e("GameLoopThread", e.toString());
                    }
                }
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder){
                gameLoopThread.setRunning(true);
                gameLoopThread.start();
            }
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }
        });
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

    }
    @Override
    protected void onDraw(Canvas canvas)
    {

        x = (int) ((canvas.getWidth() / 100) * ((lowPass(angles[2]) * 100) + 50));

        canvas.drawColor(Color.DKGRAY); //This also clears the screen
        canvas.drawBitmap(bmp, x, canvas.getHeight() - bmp.getHeight() - 20, null);

        canvas.drawText("Azimuth (Z): " + Float.toString(angles[0]),25,25, textPaint);
        canvas.drawText("Pitch (X): " + Float.toString(angles[1]),25,45, textPaint);
        canvas.drawText("Roll (Y): " + Float.toString(angles[2]),25,65, textPaint);
        canvas.drawText("X: " + Integer.toString(x),25,85,textPaint);


    }

    public static BigDecimal roundFloat(float d, int decimalPlace) {
        BigDecimal bd = new BigDecimal(Float.toString(d));
        bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
        return bd;
    }

    private float lowPass(float curValue) {
        smoothVal += (curValue - smoothVal) / smoothing;
        return smoothVal;
    }
}

游戏循环线程

public class GameLoopThread extends Thread {
    static final long FPS = 25;
    private GameView view;
    private Boolean running = false;


    public GameLoopThread(GameView view){
        this.view = view;
    }

    public void setRunning(boolean run){
        running = run;
    }

    @Override
    public void run(){
        long tickPS = 1000/FPS;
        long startTime;
        long sleepTime;

        while(running){
            Canvas c = null;
            startTime = System.currentTimeMillis();
            try {
                c = view.getHolder().lockCanvas();
                synchronized (view.getHolder()){
                    view.onDraw(c);
                }
            }

            catch (NullPointerException e) {
                Log.e("GameLoopThread", e.toString());
            }

            finally {
                if (c != null) {
                    view.getHolder().unlockCanvasAndPost(c);
                }
            }

            sleepTime = tickPS - (System.currentTimeMillis() - startTime);

            try {
                if (sleepTime > 0) {
                    sleep(sleepTime);
                }
                else {
                    sleep(10);
                }
            }
            catch (Exception e) {
                Log.e("GameLoopThread", e.toString());
            }

        }
    }
}
4

0 回答 0