当我尝试在 canvas 中旋转位图时,位图似乎没有更新

Bitmap doesn't seem to update when I try to rotate it in my canvas

我的 canvas 上有一个对象需要根据用户输入进行旋转。当用户触摸屏幕,然后移动他们的手指时,应用程序计算两个触摸事件之间的角度,这就是我需要我的位图面对的角度。

这里是一个screenshot测试Bitmap,我需要飞机的机头朝向输入确定的方向,然后随着输入的变化不断更新。

这个 GameView class 是在我的 activity 的 ContentView 中设置的:

public class GameView extends SurfaceView implements SurfaceHolder.Callback {
    MainThread thread;
    private Player player;
    private Point playerPoint;
    private float originX;
    private float originY;
    private float currX;
    private float currY;
    private float playerAngle;

    public GameView(Context context){
        super(context);

        getHolder().addCallback(this);

        thread = new MainThread(getHolder(),this);

        setBackgroundColor(getResources().getColor(R.color.background));

        setFocusable(true);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        int width = this.getWidth();
        int height = this.getHeight();

        playerPoint = new Point(width/2, height*3/5);
        player = new Player(this.getContext(), playerPoint,
                getResources().getColor(R.color.colorAccent));


        thread = new MainThread(getHolder(), this);

        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder){
        boolean retry = true;
        while(retry){
            try{
                thread.setRunning(false);
                thread.join();
            }catch(Exception e){
                e.printStackTrace();
            }
            retry = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){

        if(event.getAction() == MotionEvent.ACTION_DOWN){
            //System.out.println("Down");

            originX = event.getX();
            originY = event.getY();
        }

        currX = event.getX();
        currY = event.getY();

        //return super.onTouchEvent(event);
        return true;
    }

    public float getTouchAngle(){
        float dX = currX - originX;
        float dY = currY - originY;

        double angle = Math.atan2(dX,-dY);
        angle *= 180;
        angle /= Math.PI;
        return (float) angle;
    }

    public void update(){
        playerAngle = getTouchAngle();
        //System.out.println(playerAngle);
        player.update(playerAngle);
    }

    @Override
    public void draw(Canvas canvas){
        super.draw(canvas);

        player.draw(canvas);
    }
}

我的 MainThread 只是调用 GameView 的更新和绘制方法 class:

public class MainThread extends Thread {

    public static final int MAX_FPS = 30;
    private double averageFPS;
    private SurfaceHolder holder;
    private GameView gameView;
    private boolean running;
    public static Canvas canvas;

    public void setRunning(boolean b){
        this.running = b;
    }

    public MainThread(SurfaceHolder holder, GameView gameView){
        super();
        this.holder = holder;
        this.gameView = gameView;
        //canvas = null;
    }

    @Override
    public void run(){
        long startTime;
        long timeMillis = 1000/MAX_FPS;
        long waitTime;
        int frameCount = 0;
        long totalTime = 0;
        long targetTime = 1000/MAX_FPS;

        while(running){
            startTime = System.nanoTime();
            canvas = null;

            try{
                canvas = this.holder.lockCanvas();
                synchronized (holder){
                    this.gameView.update();
                    this.gameView.draw(canvas);
                }
            }catch(Exception e){
                e.printStackTrace();
            } finally {
                if(canvas !=null){
                    try{
                        holder.unlockCanvasAndPost(canvas);
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                }
            }

            timeMillis = (System.nanoTime() - startTime/1000000);
            waitTime = targetTime - timeMillis;
            try{
                if(waitTime > 0){
                    this.sleep(waitTime);
                }
            }catch(Exception e){
                e.printStackTrace();
            }

            totalTime += System.nanoTime() - startTime;
            frameCount++;

            if(frameCount == MAX_FPS){
                averageFPS = 1000 / ((totalTime/frameCount)/1000000);
                frameCount = 0;
                totalTime = 0;
                //System.out.println(averageFPS);
            }
        }
    }
}

然后我有我的播放器 class,这是我一直试图更新位图旋转的地方:

public class Player implements GameObject {

    //private Rect rect;
    private int color;
    private Paint paint;
    private float angle;
    private Bitmap icon;
    private Point pos;
    //private Matrix matrix;

    public Player(Context context, Point pos, int color){
        //this.rect = rect;
        this.pos = pos;
        this.color = color;
        paint = new Paint();
        //paint.setColor(color);
        //paint.setStyle(Paint.Style.FILL);
        paint.setFilterBitmap(true);
        icon = BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_action_name);
        //matrix = new Matrix();
    }

    @Override
    public void draw(Canvas canvas){
        //Matrix matrix = new Matrix();
        //matrix.setRotate(angle, 100, 100);
        //canvas.save(Canvas.ALL_SAVE_FLAG);
        canvas.rotate(-angle,pos.x,pos.y);
        System.out.println(angle);
        canvas.drawBitmap(icon,pos.x-50,pos.y-50,paint);
        //canvas.restore();
    }

    @Override
    public void update(){
    }

    public void update(float angle){
        this.angle = angle;
    }
}

我最初尝试使用 Matrix 执行旋转,一开始我让它工作,但后来我做了一些改变,从那以后就再也不能让它旋转了。

我可以看出角度计算正确,Player class 中的角度变量正在更新,因为在触摸事件之后,如果我切换到另一个应用程序然后返回到这个activity,位图朝向正确的方向。它只是不再实时更新。我不知道我做了什么。

(所有注释行都是我在尝试调整以修复它)

我发现了问题。在多次更改我的代码以尝试更新我的 canvas 之后,我尝试在我的 GameView class 中注释掉 setBackgroundColor() 方法,它突然又开始工作了.现在我只是在 Canvas 本身上设置了背景颜色,它就可以正常工作了。如果有人能解释原因,我很想听听更多