javaandroidanimationgraphicsondraw

Need help to animate a moving line with onDraw() - JAVA


I made a line via the drawLine method that starts from the bottom and goes to half the screen size. So far so good. Now I wanted to "tilt" the line to the left or right when the screen is pressed. Something like this in the picture:

enter image description here

And when pressed again have it tilt back to the other side and so on. The problem I have now is that when I tilt the line, its "trail" is visible, because I call the drawLine method multiple times.

This is my code:

public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = MainGamePanel.class.getSimpleName();

private MainThread thread;
private Paint paint;
private GameLine gameLine;

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

    getHolder().addCallback(this);

    setFocusable(true);
    paint = new Paint();
    paint.setStrokeWidth(50);
    paint.setColor(Color.WHITE);
    gameLine = new GameLine(getWidth()/2,getHeight(),getWidth()/2, getHeight()/2,paint);

    thread = new MainThread(getHolder(), this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread.setRunning(true);
    thread.start();
    gameLine = new GameLine(getWidth()/2,getHeight(),getWidth()/2, getHeight()/2,paint);

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    ...}
@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        gameLine.setTapped(true);
    }
    return super.onTouchEvent(event);
}

public void render(Canvas canvas) {
    gameLine.drawTheLine(canvas);
}
public void update(){
    gameLine.update();
}}

public class MainThread extends Thread {

private boolean running;
private MainGamePanel gamePanel;
private SurfaceHolder surfaceHolder;

public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel){
    super();
    this.gamePanel=gamePanel;
    this.surfaceHolder = surfaceHolder;
}

public void setRunning(boolean running){
    this.running = running;
}
@Override
public void run(){
    Canvas canvas;
    while (running){
        canvas = null;
        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder){
                this.gamePanel.update();
                this.gamePanel.render(canvas);
            }
        }finally {
            if(canvas != null){
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}}
public class GameLine {

private float startX;
private float startY;
private float stopX;
private float stopY;
private Paint paint;
private boolean tapped = false;


public GameLine(float startX, float startY, float stopX, float stopY, Paint paint) {
    Normal Constructor
}
public boolean getTapped(){
    return tapped;
}
public void setTapped(boolean tapped){
    this.tapped = tapped;
}
public void update(){
    if(tapped){
        this.stopX -=1;
    }
}
public void drawTheLine(Canvas canvas){

    canvas.drawLine(startX, startY,stopX, stopY,paint);
}}

I'm looking for any ideas. Did I attempt this the wrong way? How can I make the trail invisible? I'm grateful for any help. Thank you.


Solution

  • In order to eliminate the trail, you need to throw away the old canvas (to be more precise the old bitmap) and create a new one. In your example i would suggest:

    @Override
    public void run(){
        Canvas canvas;
        while (running){
            canvas = null;
            try {
                canvas = this.surfaceHolder.lockCanvas();
                synchronized (surfaceHolder){
                    this.gamePanel.update();
                    canvas = gameLine.drawTheLine();
                }
            }finally {
                if(canvas != null){
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
    

    and

    public Canvas drawTheLine(){
        Canvas canvas = new Canvas();
        canvas.drawLine(startX, startY,stopX, stopY,paint);
        return canvas;
    }