簡體   English   中英

在自定義視圖中對Drawable進行動畫處理

[英]Animate a Drawable in a custom view

我正在嘗試在自定義視圖中為ShapeDrawable設置動畫。 但是我不確定完成此任務的最佳方法是什么。

我是否應該嘗試在路徑上繪制棋子並調用invalidate()直到到達目標方塊? 還是使用AsyncTask或Handler處理更好的方法?

這是我的代碼,為了使其可讀性,我省略了很多方法和變量。

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

}

謝謝您的幫助。

枯萎病

您應該為您的應用程序創建兩個線程。 UI線程是一個線程,它僅以當前狀態繪制板。 另一個線程是游戲引擎或動畫線程,用於移動板上的項目。

第一個線程以您希望的幀速率運行,第二個線程應以更快的速度運行。 這樣,您實際上不必親自處理動畫,因為UI線程僅按當前狀態繪制板。 在引擎線程中,您可以在線程的每個循環中更新游戲,棋盤,棋子的狀態。

用這種方式做事有很多好處。 首先,如果引擎線程在某種計算中陷入困境,游戲的幀率將不會降低。 其次,它允許您以一種簡化調試的方式將圖形從游戲中抽象出來。

以進度條為例。 假設您嘗試創建一個帶有進度條的文件上傳器,但只有一個線程。 因此,您可以啟動進度條,然后開始上傳文件。 如果上載過程受阻,則必須等待文件完成上載,然后才能更新進度條,從而使進度條無用。 但是,如果您使用兩個線程執行此操作,則可以對其進行設置,以便一個線程僅根據某個公共變量更新進度條圖形。 另一個胎面負責執行動作並更新進度變量。

查看這些鏈接以獲取更多信息:

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

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

http://www.helloandroid.com/tutorials/using-threads-and-progress對話框

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM