I have an object on my canvas that I need to rotate based on user input. When the user touches the screen, and then moves their finger, the app calculates the angle between the two touch events, and that is the angle I need my Bitmap to face.

Here is a screenshot with a test Bitmap, I need the nose of the plane to face the direction determined by the input, and then update constantly as the input changes.

This GameView class is set at the ContentView for my activity:

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);}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}@Overridepublic 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();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder){boolean retry=true;while(retry){try{thread.setRunning(false);thread.join();}catch(Exception e){e.printStackTrace();}retry=false;}}@Overridepublic 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);}@Overridepublic void draw(Canvas canvas){super.draw(canvas);player.draw(canvas);}}

I have my MainThread which just calls the update and draw methods for the 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;}@Overridepublic 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);}}}}

And then I have my Player class, which is where I have been trying to get the Bitmap rotation to update:

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();}@Overridepublic 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();}@Overridepublic void update(){}public void update(float angle){this.angle=angle;}}

I originally tried to perform the rotation using a Matrix, and I had it working at first, but then I made changes and haven't been able to get it to rotate at all since.

I can tell that the angle is getting computed properly, and the angle variable in the Player class is getting updated, because after a touch event, if I switch to a different app then go back into this activity, the bitmap is facing the correct direction. It just isn't updating in realtime anymore. I have no clue what I did.

(all the commented lines are me trying to tweak things to fix it)

    I found the issue. After changing up my code several times to try and get my canvas to update, I tried commenting out the setBackgroundColor() method in my GameView class, and it suddenly started working again. Now I just set the background color on the Canvas itself and it works as it should. If anyone could explain why, I'd love to hear more

      Your Answer


      By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

      Not the answer you're looking for? Browse other questions tagged or ask your own question.