Android draw ball trail

Ircover :

There are balls in my app that just fly through display. They draws as I want. But now I want to draw the trail behind them.

All I could make is just drawing by canvas.drawPath something like following picture:

I have it now

But it is not what I want. It should have pointed tail and gradient color like this:

I want that

I have no idea how to make it. Tried BitmapShader - couldn't make something right. Help, please.

Code:

First of all, there is Point class for position on display:

class Point {
    float x, y;
    ...
}

And trail is stored as queue of Point:

private ConcurrentLinkedQueue<Point> trail;

It doesn't matter how it fills, just know it has size limit:

trail.add(position);
if(trail.size() > TRAIL_MAX_COUNT) {
    trail.remove();
}

And drawing happened in DrawTrail method:

private void DrawTrail(Canvas canvas) {
    trailPath.reset();
    boolean isFirst = true;
    for(Point p : trail) {
        if(isFirst) {
            trailPath.moveTo(p.x, p.y);
            isFirst = false;
        } else {
            trailPath.lineTo(p.x, p.y);
        }
    }
    canvas.drawPath(trailPath, trailPaint);
}

By the way, trailPaint is just really fat paint :)

trailPaint = new Paint();
trailPaint.setStyle(Paint.Style.STROKE);
trailPaint.setColor(color);
trailPaint.setStrokeWidth(radius * 2);
trailPaint.setAlpha(150);
Ircover :

I found solution. But still think it is not the best one.

First of all there are my class fields used for that task.

static final int TRAIL_MAX_COUNT = 50; //maximum trail array size
static final int TRAIL_DRAW_POINT = 30; //number of points to split the trail for draw

private ConcurrentLinkedQueue<Point> trail;
private Paint[] trailPaints;
private float[][] trailPoss, trailTans;
private Path trailPath;

Additionally to trailPath object I used PathMeasure object to split path to multiple equal parts.

After filling trail array object added call of trail calculating function.

lastTrailAdd = now;
trail.add(pos.Copy());
if (trail.size() > TRAIL_MAX_COUNT) {
    trail.remove();
}
FillTrail();

Then my FillTrail function.

private void FillTrail() {
    trailPath.reset();
    boolean isFirst = true;
    for(Point p : trail) {
        if(isFirst) {
            trailPath.moveTo(p.x, p.y);
            trailPoss[0][0] = p.x;
            trailPoss[0][1] = p.y;
            isFirst = false;
        } else {
            trailPath.lineTo(p.x, p.y);
        }
    }
    PathMeasure path = new PathMeasure(trailPath, false);
    float step = path.getLength() / TRAIL_DRAW_POINT;
    for(int i=0; i<TRAIL_DRAW_POINT; i++) {
        path.getPosTan(step * i, trailPoss[i], trailTans[i]);
    }
}

It separated from drawing thread. Next code is drawing function.

private void DrawTrail(Canvas canvas) {
    if(trail.size() > 1) {
        float prevWidthHalfX = 0f, prevWidthHalfY = 0f, prevX = 0f, prevY = 0f;
        Path trailStepRect = new Path();
        boolean isFirst = true;
        for (int i = 0; i < TRAIL_DRAW_POINT; i++) {
            float currWidthHalf = (float) (radius) * i / TRAIL_DRAW_POINT / 2f,
                    currWidthHalfX = currWidthHalf * trailTans[i][1],
                    currWidthHalfY = currWidthHalf * trailTans[i][0],
                    currX = trailPoss[i][0], currY = trailPoss[i][1];
            if (!isFirst) {
                trailStepRect.reset();
                trailStepRect.moveTo(prevX - prevWidthHalfX, prevY + prevWidthHalfY);
                trailStepRect.lineTo(prevX + prevWidthHalfX, prevY - prevWidthHalfY);
                trailStepRect.lineTo(currX + currWidthHalfX, currY - currWidthHalfY);
                trailStepRect.lineTo(currX - currWidthHalfX, currY + currWidthHalfY);
                canvas.drawPath(trailStepRect, trailPaints[i]);
            } else {
                isFirst = false;
            }
            prevX = currX;
            prevY = currY;
            prevWidthHalfX = currWidthHalfX;
            prevWidthHalfY = currWidthHalfY;
        }
    }
}

Main point of this is drawing trail by parts with different paints. Closer to ball - wider the trail. I think I will optimise it, but it is allready work.

If you want to watch how it looks just install my app from google play.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=451007&siteId=1