2014-01-19 63 views
0

我正在嘗試開發簡單的棋盤遊戲。該董事會是9×9大小的領域。球出現在田野上,當用戶用球點擊球時,球開始跳躍。我以兩種方式實現了動畫。第一個工作正在進行,但添加另一個動畫(如小小的伸展或其他東西)並不容易。而第二個,似乎更好(有使用AnimatorSet)不起作用。當用戶用球點擊球時,球消失。我不知道爲什麼:-(AnimatorSet不可用的可繪製動畫 - 可繪製消失

第一類實現了板,這是觀的孩子:

public class BoardView extends View { 
    ... 

    /** 
    * Initializes fields of the board. 
    */ 
    private void initializeFields() { 
    this.fields = new ArrayList<Field>(); 

    for (int row = 0; row < BoardView.FIELDS_NUMBER; row++) { 
     for (int column = 0; column < BoardView.FIELDS_NUMBER; column++) { 
      this.fields.add(new Field(this, row, column)); 
     } 
    } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
    canvas.drawColor(BoardView.COLOR_ACTIVITY); 

    if (this.fields == null) { 
     this.initializeFields(); 
    } 

    for (int i = 0; i < this.fields.size(); i++) { 
     this.fields.get(i).draw(canvas); 
    } 
    } 

    ... 
} 

第二個實現了場:

public class Field { 
    ... 

    /** 
    * Draws itself on the screen. 
    * 
    * @param Canvas canvas 
    */ 
    public void draw(Canvas canvas) { 
     Rect field = this.getRect(); 
     int round = (int)Math.floor(this.board.getFieldSize()/4); 

     this.board.getPainter().setStyle(Paint.Style.FILL); 
     this.board.getPainter().setColor(Field.COLOR_DEFAULT); 

     // draw field 
     canvas.drawRoundRect(new RectF(field), round, round, this.board.getPainter()); 

     // draw selected field 
     if (this.selected) { 
     this.board.getPainter().setColor(Field.COLOR_SELECTED); 
     canvas.drawRoundRect(new RectF(field), round, round, this.board.getPainter()); 
     } 

     // draw ball 
     if (this.ball != null) { 
     Point fieldOrigin = new Point(field.left, field.top); 

     if (this.selected) { 
      this.ball.animate(canvas, fieldOrigin); 
     } else { 
      this.ball.draw(canvas, fieldOrigin); 
     } 
     } 
    } 

    ... 
} 

而最後一個實現球: 這裏是第一種方法,它完全有效,但它不夠靈活:

public class Ball { 
    ... 

    /** 
    * Draws itself on the screen. 
    * 
    * @param Canvas canvas 
    * @param Point fieldOrigin 
    */ 
    public void draw(Canvas canvas, Point fieldOrigin) { 
     // set painter 
     Paint painter = this.field.getBoard().getPainter(); 

     painter.setStyle(Paint.Style.FILL); 
     painter.setColor(Ball.COLORS[this.color]); 

     // calculate parameters 
     float halfSize = this.field.getBoard().getFieldSize()/2; 
     float cX = fieldOrigin.x + halfSize; 
     float cY = fieldOrigin.y + halfSize + this.dy; 
     float radius = 0.6f * halfSize; 

     // draw circle 
     canvas.drawCircle(cX, cY, radius, painter); 

     // the code continues, because of the shadow and light simulation (radial gradients) 
    } 

    /** 
    * Draws jumping animation. 
    * 
    * @param Canvas canvas 
    * @param Point fieldOrigin 
    */ 
    public void animate(Canvas canvas, Point fieldOrigin) { 
     float currentDy = (this.dy - 0.1f); 

     this.setDy((float)Math.abs(Math.sin(currentDy)) * (-0.15f * this.field.getBoard().getFieldSize())); 
     this.draw(canvas, fieldOrigin); 
     this.setDy(currentDy); 

     try { 
     Thread.sleep(Ball.ANIMATION_DELAY); 
     } catch (InterruptedException e) {} 

     this.field.invalidate(); 
    } 

    ... 
} 

如您所見,動畫是通過休眠當前線程並更改參數dy來實現的。

第二種方法是顯示在球場上的球,但動畫不能正常工作,因爲我在文章的開頭說(點擊之後,球消失):

public class BallShape { 
    private Field field; 
    private LayerDrawable ball; 
    private int color; 
    private float diameter, 
       x, y;   // top left corner - THE GETTERS AND SETTERS ARE IMPLEMENTED (because of Animator) 
    ... 

    /** 
    * Initializes the ball. 
    * 
    * @param Field field 
    * @param int color 
    */ 
    public BallShape(Field field, int color) { 
     this.field = field; 
     this.color = ((color == Ball.COLOR_RANDOM) ? Ball.randomColor() : color); 

     // create ball 
     float halfSize = this.field.getBoard().getFieldSize()/2; 

     this.diameter = 0.6f * field.getBoard().getFieldSize(); 
     float radius = this.diameter/2; 

     Rect fieldArea = field.getRect(); 
     this.x = fieldArea.left + halfSize - radius; 
     this.y = fieldArea.top + halfSize - radius; 

     // color circle 
     OvalShape circleShape = new OvalShape(); 
     circleShape.resize(this.diameter, this.diameter); 

     ShapeDrawable circle = new ShapeDrawable(circleShape); 
     this.initPainter(circle.getPaint()); 

     // the code continues, because of the shadow and light simulation (radial gradients) 

     // compound shape - ball 
     ShapeDrawable[] compound = { circle };//, shadow, light }; 
     this.ball = new LayerDrawable(compound); 
    } 

    /** 
    * Draws itself on the screen. 
    * 
    * @param Canvas canvas 
    * @param Point fieldOrigin 
    */ 
    public void draw(Canvas canvas, Point fieldOrigin) { 
     canvas.save(); 

     canvas.translate(this.x, this.y); 
     this.ball.draw(canvas); 

     canvas.restore(); 
    } 

    /** 
    * Draws jumping animation. 
    * 
    * @param Canvas canvas 
    * @param Point fieldOrigin 
    */ 
    public void animate(Canvas canvas, Point fieldOrigin) { 
     // common data 
     float halfSize = this.field.getBoard().getFieldSize()/2; 
     float radius = this.diameter/2; 

     float startY = fieldOrigin.y + halfSize - radius; 
     float endY = startY - halfSize + 2; 

     // bounce animation 
     ValueAnimator bounceAnimation = ObjectAnimator.ofFloat(this, "y", startY, endY); 
     bounceAnimation.setDuration(BallShape.ANIMATION_LENGTH); 
     bounceAnimation.setInterpolator(new AccelerateInterpolator()); 
     bounceAnimation.setRepeatCount(ValueAnimator.INFINITE); 
     bounceAnimation.setRepeatMode(ValueAnimator.REVERSE); 
    //bounceAnimation.start(); 

     // animation 
     AnimatorSet bouncer = new AnimatorSet(); 
     bouncer.play(bounceAnimation); 

     // start the animation 
     bouncer.start(); 
    } 

    ... 
} 

任何想法,爲什麼它的不工作?我做錯了什麼? 非常感謝你。

+0

我會解決的兩件事。首先你用draw()方法開始動畫。您應該在onClick()中啓動它,或者至少將this.selected設置爲false,以便在每次繪製()時不啓動它。其次,在您重視動畫師更改屬性後,您需要重繪BallShape。否則什麼都不會改變。例如,你可以定義setY(float Y)方法,在那裏改變Y並且調用invalidate()。 –

+0

太棒了!我剛剛將評論移至答案。你現在可以接受它。 –

回答

0

我會修復兩件事情。

首先你用draw()方法開始動畫。您應該使用onClick()啓動它,或者至少將此選項設置爲false,以便每個draw()都不啓動它。其次,在您的值動畫師更改屬性後,您需要重繪BallShape。否則什麼都不會改變。例如,您可以定義setY(float Y)方法,在那裏更改Y並致電invalidate()

+0

非常感謝,現在正在工作:-) – Honza