当我尝试在 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 本身上设置了背景颜色,它就可以正常工作了。如果有人能解释原因,我很想听听更多
我的 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 本身上设置了背景颜色,它就可以正常工作了。如果有人能解释原因,我很想听听更多