我已经研究了好几天,没有找到一个好的解决方案(至少对我来说)。
基本上,我需要做的是绘制一条动画虚线,这将代表基本游戏的导弹轨迹。该轨迹将接受起始、中间和最终的x,y。我刚开始读了很多关于动画曲线甚至直线的问答,但与我必须做的相比,它们看起来真的很复杂。
我有一个带有onclick
监听器的按钮,它可以触发导弹发射,但到目前为止,它只是画静态线,没有任何动画。
你还记得这个吗?这就是我想要实现的目标:http://www.youtube.com/watch?v=UDc3ZEKl-Wc
香蕉的轨迹没有画出来,但是,你有这个想法。
再次,从你的例子开始,我试图使用数组和for循环同时绘制曲线,但我得到的是,有时(并非总是)应用程序会因nullpointer异常而崩溃,不知道为什么。我做错了什么?这是我的代码:
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();
}
}
}
假设你有一个画布可以绘制,并且你想跟踪这个代码的路径应该可以为它制作动画。
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
检索一个段,并将其添加到当前应绘制的路径中。
感谢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);
}
}