2014-04-11 222 views
2

我一直在這個好幾天沒有找到一個好的解決方案(至少對我來說)。安卓繪製動畫虛線曲線

基本上我需要做的就是繪製動畫虛線,那將是一個導彈彈道一個基本的遊戲。該軌跡將接受x,y的開始,中間和最終。我讀了許多關於動畫曲線甚至直線開始的Q/A,但與我必須做的相比,它們看起來非常複雜。

我有一個onclick監聽器觸發了導彈發射按鈕,但是到現在爲止,它只是繪製靜態行沒有任何動畫。

你還記得嗎?這就是我想達到的效果: http://www.youtube.com/watch?v=UDc3ZEKl-Wc

香蕉的軌跡不畫,但,你有想法。


在這裏,從您的範例開始我試圖繪製使用數組和循環同步的曲線,但我得到的是,有時,不總是與一個空指針異常應用程序崩潰,不知道爲什麼。我究竟做錯了什麼?這裏是我的代碼:

public class DrawDottedCurve extends View { 

    Path[] path = new Path[8]; 
    Path[] drawingPath = new Path[8]; 
    PathMeasure[] measure = new PathMeasure[8]; 
    Path[] segmentPath = new Path[8]; 
    float[] length = new float[8]; 
    float[] start = new float[8]; 
    float[] percent = new float[8]; 
    Paint paint = new Paint(); 
    float x1; 
    float y1; 
    float x3; 
    float y3; 
    long k = 0; 
    Canvas canvas; 
    Random r = new Random(); 

    public DrawDottedCurve(Context context, int a, int b, int c, int d) { 
     super(context); 
     x1 = a; 
     y1 = b; 
     x3 = c; 
     y3 = d; 

     paint.setAlpha(255); 
     paint.setStrokeWidth(2); 
     paint.setColor(Color.RED); 
     paint.setStyle(Style.STROKE); 
     paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50)); 

     for (int i = 0; i < 8; i++) { 
      k = r.nextInt(100 - 30) + 30; 
      path[i] = new Path(); 
      path[i].moveTo(x1 + k, y1 + k); // 
      path[i].quadTo((x3 + k - x1 + k)/2, (y3 + k - y1 + k)/2, 
        x3 + k, y3 + k); // Calculate Bezier Curves 
     } 

     final long DRAW_TIME = 10000; 
     CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) { 

      @Override 
      public void onTick(long millisUntilFinished) { 
       Log.d("Timer", "Inizio"); 
       for (int i = 0; i < 8; i++) { 
        start[i] = 0; 
        measure[i] = new PathMeasure(); 
        measure[i].setPath(path[i], false); 

        percent[i] = ((float) (DRAW_TIME - millisUntilFinished)) 
          /(float) DRAW_TIME; 

        segmentPath[i] = new Path(); 
        drawingPath[i] = new Path(); 
        length[i] = measure[i].getLength() * percent[i]; 
        measure[i].getSegment(start[i], length[i], segmentPath[i], 
          true); 
        start[i] = length[i]; 
        drawingPath[i].addPath(segmentPath[i]); 


       } 
       invalidate(); 
; 
      } 

      @Override 
      public void onFinish() { 
       for (int i = 0; i < 8; i++) { 
        measure[i].getSegment(start[i], measure[i].getLength(), 
          segmentPath[i], true); 
        drawingPath[i].addPath(segmentPath[i]); 


       } 

       invalidate(); 
       Log.d("Timer", "Fine"); 
      } 

     }; 
     timer.start(); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     for (int i = 0; i < 8; i++) { 
      canvas.drawPath(drawingPath[i], paint); 
      invalidate(); 

     } 

    } 
} 
+0

計算一個曲線上的點,Bezier曲線例如並一個接一個地繪製它們...... – ElDuderino

回答

0

假設你有一個畫布上繪製,並要跟蹤這個代碼應該做的工作,爲動畫它的路徑。

private void init() { 
    missilePath = new Path(); 
    missileDrawPath = new Path(); 

    mPaint = new Paint(); 
    mPaint.setStrokeWidth(3); 
    mPaint.setColor(Color.BLACK); 
    mPaint.setStyle(Style.STROKE); 
    mPaint.setAntiAlias(true); 

    PathEffect dashEffect = new DashPathEffect(new float[] {2, 4}, 0); 
    mPaint.setPathEffect(dashEffect); 

    final long DRAW_TIME = 5000; 
    timer = new CountDownTimer(DRAW_TIME, 100) { 
     PathMeasure measure = new PathMeasure(); 
     Path segmentPath = new Path(); 
     float start = 0; 

     @Override 
     public void onTick(long millisUntilFinished) { 
      measure.setPath(missilePath, false); 
      float percent = ((float) (DRAW_TIME - millisUntilFinished))/(float) DRAW_TIME; 
      float length = measure.getLength() * percent; 
      measure.getSegment(start, length, segmentPath, true); 
      start = length; 
      missileDrawPath.addPath(segmentPath); 
      invalidate(); 
     } 

     @Override 
     public void onFinish() { 
      measure.getSegment(start, measure.getLength(), segmentPath, true); 
      missileDrawPath.addPath(segmentPath); 
      invalidate(); 
     } 
    }; 
    timer.start(); 
} 


@Override 
public void onDraw(Canvas c) { 
    super.onDraw(c); 
    c.drawPath(missileDrawPath, mPaint); 
} 

基本上計時器得到啓動,並根據段被從missilePath檢索並添加到應當當前繪製的路徑所經過的時間。

+0

我將在接下來的幾天內實現該代碼並讓您知道。現在感謝 – realpclaudio

0

謝謝你,真的很好SceLus,這裏的人,最終停留在同一個問題的全部代碼。

類構造函數採用Bezier曲線起始和最終X和Y的作爲輸入,並簡單地計算中間控制點,則根據SceLus代碼繪製的一切。

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.DashPathEffect; 
import android.graphics.Paint; 
import android.graphics.Paint.Style; 
import android.graphics.Path; 
import android.graphics.PathMeasure; 
import android.os.CountDownTimer; 
import android.view.View; 

public class DrawDottedCurve extends View { 

    Path path = new Path(); 
    Path drawingPath = new Path(); 
    Paint paint = new Paint(); 
    float x1; 
    float y1; 
    float x3; 
    float y3; 

    public DrawDottedCurve(Context context, int a, int b, int c, int d) { 
     super(context); 

     x1 = a; 
     y1 = b; 
     x3 = c; 
     y3 = d; 

     paint.setAlpha(255); 
     paint.setStrokeWidth(2); 
     paint.setColor(Color.RED); 
     paint.setStyle(Style.STROKE); 
     paint.setPathEffect(new DashPathEffect(new float[] { 2, 4 }, 50)); 

     path.moveTo(x1, y1); // 
     path.quadTo((x3 - x1)/2, (y3 - y1)/2, x3, y3); // Calculate Bezier Curve 

     final long DRAW_TIME = 10000; 
     CountDownTimer timer = new CountDownTimer(DRAW_TIME, 100) { 
      PathMeasure measure = new PathMeasure(); 
      Path segmentPath = new Path(); 
      float start = 0; 

      @Override 
      public void onTick(long millisUntilFinished) { 
       measure.setPath(path, false); 
       float percent = ((float) (DRAW_TIME - millisUntilFinished)) 
         /(float) DRAW_TIME; 
       float length = measure.getLength() * percent; 
       measure.getSegment(start, length, segmentPath, true); 
       start = length; 
       drawingPath.addPath(segmentPath); 
       invalidate(); 
      } 

      @Override 
      public void onFinish() { 
       measure.getSegment(start, measure.getLength(), segmentPath, 
         true); 
       drawingPath.addPath(segmentPath); 
       invalidate(); 
      } 
     }; 
     timer.start(); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     canvas.drawPath(drawingPath, paint); 
    } 
}