简体   繁体   English

在自定义视图中对Drawable进行动画处理

[英]Animate a Drawable in a custom view

I'm trying to animate a ShapeDrawable in a custom view. 我正在尝试在自定义视图中为ShapeDrawable设置动画。 But I am not sure what the best method is to accomplish this task. 但是我不确定完成此任务的最佳方法是什么。

Should I try and draw a pawn on a path and call invalidate() until it has reached the destination square? 我是否应该尝试在路径上绘制棋子并调用invalidate()直到到达目标方块? Or is there some better method using maybe an AsyncTask or Handler? 还是使用AsyncTask或Handler处理更好的方法?

Here is my code, I have omitted a lot of methods and variables in order to make it readable. 这是我的代码,为了使其可读性,我省略了很多方法和变量。

public class CheckerBoard extends View {

    public enum State implements Parcelable {
        EMPTY(0), WHITE(1), BLACK(2);
    }

        private final State[][] boardStates = new State[SIZE][SIZE];

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(bgColor);
        for (int y = 0; y < SIZE; y++) {
            for (int x = 0; x < SIZE; x++) {
                if ((y % 2 == 0 && x % 2 != 0) || (y % 2 != 0 && x % 2 == 0)) {
                    drawRect(x, y, canvas);
                    drawPawn(x, y, canvas);
                }
            }
        }
    }

    private void drawRect(int x, int y, Canvas c) {
    }

    private void drawPawn(int x, int y, Canvas c) {
    }

    private void init() {
        setupBoard();
        pawnLinePaint.setStyle(Paint.Style.STROKE);
        wPawnDrawable.getPaint().setColor(wColor);
        wPawnDrawable.getPaint().setShadowLayer(tileSize + 2, 4, 4, Color.GRAY);
        bPawnDrawable.getPaint().setColor(bColor);
        bPawnDrawable.getPaint().setShadowLayer(tileSize + 2, 4, 4, Color.GRAY);
        playerState = startState;
    }

    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int x = (int) (event.getX() / tileSize);
                int y = (int) (event.getY() / tileSize);
                if (selection[0] >= 0) { // A tile is already selected
                    if (isValidMove(selection[0], selection[1], x, y)) {
                        makeMove(x, y);
                        clearSelection();
                        switchPlayer();
                        invalidate();
                    }

                } else { // New selection
                    if (isValidSelection(x, y)) {
                        selection[0] = x;
                        selection[1] = y;
                        invalidate();
                    }
                }

                return true;
            default:
                return super.onTouchEvent(event);
        }
    }

    private void makeMove(int x, int y) {
        // Move the pawn to the new square
        boardStates[y][x] = boardStates[selection[1]][selection[0]];
        // Old square is now empty
        boardStates[selection[1]][selection[0]] = State.EMPTY;  
    }

    private void switchPlayer() {
        playerState = playerState == State.WHITE ? State.BLACK : State.WHITE;
    }

    public CheckerBoard(Context context) {
        super(context);
        init();
    }

    public CheckerBoard(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CheckerBoard(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }


    private class Pawn extends ShapeDrawable {
        public Pawn() {
            super(new OvalShape());
        }

        public void drawWithCircles(Canvas canvas, float x, float y){
            super.draw(canvas);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding,
                    pawnLinePaint);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding * 6,
                    pawnLinePaint);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding * 8,
                    pawnLinePaint);
        }
    }

}

Thank you for your help. 谢谢您的帮助。

Blight 枯萎病

You should create two threads for your application. 您应该为您的应用程序创建两个线程。 One thread is the UI thread that only draws the board in its current state. UI线程是一个线程,它仅以当前状态绘制板。 The other thread is the Game engine or animation thread that moves the items on the board. 另一个线程是游戏引擎或动画线程,用于移动板上的项目。

The first thread runs at whatever your desired frame rate is and the 2nd thread should run considerably faster. 第一个线程以您希望的帧速率运行,第二个线程应以更快的速度运行。 This way you don't actually have to handle the animation yourself as the UI thread just draws the board as it currently is. 这样,您实际上不必亲自处理动画,因为UI线程仅按当前状态绘制板。 In your engine thread you update the state of the game,board,chess pieces, every cycle of the thread. 在引擎线程中,您可以在线程的每个循环中更新游戏,棋盘,棋子的状态。

Doing things this way has a couple of benefits. 用这种方式做事有很多好处。 First your game's framerate won't drop if the Engine thread gets bogged down in some sort of computation. 首先,如果引擎线程在某种计算中陷入困境,游戏的帧率将不会降低。 Second it allows you to abstract the drawing away from the game in a way that will make debugging much easier. 其次,它允许您以一种简化调试的方式将图形从游戏中抽象出来。

Take a progress bar for example. 以进度条为例。 Let say you tried to create a file uploader with a progress bar but only had one thread. 假设您尝试创建一个带有进度条的文件上传器,但只有一个线程。 So you start the progress bar then start uploading the file. 因此,您可以启动进度条,然后开始上传文件。 If the upload process is blocking then you have to wait for the file to finish uploading before you can update the progress bar, essentially rendering the progress bar useless. 如果上载过程受阻,则必须等待文件完成上载,然后才能更新进度条,从而使进度条无用。 But if you did this with two threads then you could set it up so one thread simply updates the progress bars graphics based upon some common variable. 但是,如果您使用两个线程执行此操作,则可以对其进行设置,以便一个线程仅根据某个公共变量更新进度条图形。 The other tread is responsible for performing an action and updating the progress variable. 另一个胎面负责执行动作并更新进度变量。

Check out these links for more info: 查看这些链接以获取更多信息:

http://obviam.net/index.php/the-android-game-loop/ http://obviam.net/index.php/the-android-game-loop/

http://www.rbgrn.net/content/54-getting-started-android-game-development http://www.rbgrn.net/content/54-getting-started-android-game-development

http://www.helloandroid.com/tutorials/using-threads-and-progressdialog http://www.helloandroid.com/tutorials/using-threads-and-progress对话框

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM