1

ここ数日、私はセンサーとキャンバスをいじっていました。

これまでのところ、デバイスの角度に基づいてビットマップの位置を制御することができました。

アプリが動作する方法は、方向データを取得し、デバイスの傾きに応じて、ビットマップを画面上で左または右に移動することです。

私は Android 4.2.2 (AOKP) を実行している Samsung Galaxy S II GT-i9100 でほとんどのテストを行っていますが、再開時にアプリがクラッシュすることを除けば、アプリはほとんど問題なく動作します (原因はわかっていると思います)。

私が抱えている問題は次のとおりです。

Sony Xperia Z (android 4.1.2 を実行、Sony の在庫) で同じコードを実行しようとすると、アプリ全体が途切れ途切れになり (ビットマップがほとんど動かない)、センサー データの取得が途切れ途切れ/遅いためだと思います。私の友人の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