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

时间:2018-02-13 17:14:28

标签: java android android-canvas

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

这是一个带有测试位图的screenshot,我需要平面的鼻子面向输入确定的方向,然后随着输入的变化不断更新。

此GameView类在我的活动的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类的更新和绘制方法:

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

然后我有了我的Player类,这是我一直试图让Bitmap旋转更新的地方:

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类中的角度变量正在更新,因为在触摸事件之后,如果我切换到另一个应用程序然后返回到此活动,则位图面临正确的方向。它不再是实时更新。我不知道我做了什么。

(所有注释的行都是我试图调整一些东西来修复它)

1 个答案:

答案 0 :(得分:0)

我发现了这个问题。在多次更改我的代码以尝试让我的画布更新后,我尝试在我的setBackgroundColor()课程中注释掉GameView方法,然后突然又开始工作了。现在我只是在Canvas上设置背景颜色,它可以正常工作。如果有人能解释原因,我很乐意听到更多