libGdx专题

LibGdx绘制圆形进度条

2021-08-28  本文已影响0人  大旺旺的弟弟小旺旺

案例一:

public class RoundProgress extends Actor {
    private float UWidth;
    private float VHeight;
    float progress;
    TextureRegion region;
    private Texture regionTexture;
    private float regionU;
    private float regionU2;
    private float regionV;
    private float regionV2;

    public RoundProgress(Texture texture) {
        setRegion(new TextureRegion(texture));
    }

    public RoundProgress(TextureRegion region2) {
        setRegion(region2);
    }

    public void setRegion(TextureRegion region2) {
        this.region = region2;
        setSize((float) region2.getRegionWidth(), (float) region2.getRegionHeight());
        this.regionTexture = region2.getTexture();
        this.regionU = region2.getU();
        this.regionV = region2.getV();
        this.regionU2 = region2.getU2();
        this.regionV2 = region2.getV2();
        this.UWidth = this.regionU2 - this.regionU;
        this.VHeight = this.regionV2 - this.regionV;
        System.out.println(tanDeg(45.0f));
    }

    public void setProgress(float progress2) {
        this.progress = progress2;
    }

    public float tanDeg(float degrees) {
        return MathUtils.sinDeg(degrees) / MathUtils.cosDeg(degrees);
    }

    @Override // com.badlogic.gdx.scenes.scene2d.Actor
    public void draw(Batch batch, float parentAlpha) {
        if (this.region != null) {
            this.progress %= 360.0f;
            this.progress += 360.0f;
            this.progress %= 360.0f;
            Color oldcolor = batch.getColor();
            Color newcolor = getColor();
            batch.setColor(newcolor.r, newcolor.g, newcolor.b, newcolor.a * parentAlpha);
            if (this.progress < 45.0f) {
                float w1 = tanDeg(this.progress);
                batch.draw(this.regionTexture, new float[]{(getX() + (getWidth() / 2.0f)) - ((getWidth() / 2.0f) * w1), getY() + getHeight(), batch.getPackedColor(), ((this.regionU2 + this.regionU) / 2.0f) - ((this.UWidth / 2.0f) * w1), this.regionV, (getX() + (getWidth() / 2.0f)) - ((getWidth() / 2.0f) * w1), getY() + getHeight(), batch.getPackedColor(), ((this.regionU2 + this.regionU) / 2.0f) - ((this.UWidth / 2.0f) * w1), this.regionV, getX() + (getWidth() / 2.0f), getY() + getHeight(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV2 + this.regionV) / 2.0f}, 0, 20);
            } else if (this.progress < 135.0f) {
                float h1 = tanDeg(90.0f - this.progress);
                batch.draw(this.regionTexture, new float[]{getX(), getY() + (getHeight() / 2.0f) + ((getHeight() / 2.0f) * h1), batch.getPackedColor(), this.regionU, ((this.regionV2 + this.regionV) / 2.0f) - ((this.VHeight / 2.0f) * h1), getX(), getY() + getHeight(), batch.getPackedColor(), this.regionU, this.regionV, getX() + (getWidth() / 2.0f), getY() + getHeight(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV2 + this.regionV) / 2.0f}, 0, 20);
            } else if (this.progress < 225.0f) {
                batch.draw(this.regionTexture, new float[]{getX(), getY() + (getHeight() / 2.0f), batch.getPackedColor(), this.regionU, (this.regionV2 + this.regionV) / 2.0f, getX(), getY() + getHeight(), batch.getPackedColor(), this.regionU, this.regionV, getX() + (getWidth() / 2.0f), getY() + getHeight(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV2 + this.regionV) / 2.0f}, 0, 20);
                float w12 = tanDeg(this.progress - 180.0f);
                batch.draw(this.regionTexture, new float[]{getX(), getY(), batch.getPackedColor(), this.regionU, this.regionV2, getX(), getY() + (getHeight() / 2.0f), batch.getPackedColor(), this.regionU, (this.regionV + this.regionV2) / 2.0f, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV + this.regionV2) / 2.0f, getX() + (getWidth() / 2.0f) + ((getWidth() * w12) / 2.0f), getY(), batch.getPackedColor(), ((this.regionU2 + this.regionU) / 2.0f) + ((this.UWidth / 2.0f) * w12), this.regionV2}, 0, 20);
            } else if (this.progress < 315.0f) {
                batch.draw(this.regionTexture, new float[]{getX(), getY(), batch.getPackedColor(), this.regionU, this.regionV2, getX(), getY() + getHeight(), batch.getPackedColor(), this.regionU, this.regionV, getX() + (getWidth() / 2.0f), getY() + getHeight(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV, getX() + (getWidth() / 2.0f), getY(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV2}, 0, 20);
                float h12 = tanDeg(this.progress - 270.0f);
                batch.draw(this.regionTexture, new float[]{getX() + (getWidth() / 2.0f), getY(), batch.getPackedColor(), (this.regionU + this.regionU2) / 2.0f, this.regionV2, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU + this.regionU2) / 2.0f, (this.regionV + this.regionV2) / 2.0f, getX() + getWidth(), getY() + (getHeight() / 2.0f) + ((getHeight() / 2.0f) * h12), batch.getPackedColor(), this.regionU2, ((this.regionV + this.regionV2) / 2.0f) - ((this.VHeight / 2.0f) * h12), getX() + getWidth(), getY(), batch.getPackedColor(), this.regionU2, this.regionV2}, 0, 20);
            } else {
                batch.draw(this.regionTexture, new float[]{getX(), getY(), batch.getPackedColor(), this.regionU, this.regionV2, getX(), getY() + getHeight(), batch.getPackedColor(), this.regionU, this.regionV, getX() + (getWidth() / 2.0f), getY() + getHeight(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV, getX() + (getWidth() / 2.0f), getY(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV2}, 0, 20);
                batch.draw(this.regionTexture, new float[]{getX() + (getWidth() / 2.0f), getY(), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, this.regionV2, getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV + this.regionV2) / 2.0f, getX() + getWidth(), getY() + (getHeight() / 2.0f), batch.getPackedColor(), this.regionU2, (this.regionV + this.regionV2) / 2.0f, getX() + getWidth(), getY(), batch.getPackedColor(), this.regionU2, this.regionV2}, 0, 20);
                float w13 = tanDeg(360.0f - this.progress);
                batch.draw(this.regionTexture, new float[]{getX() + (getWidth() / 2.0f), getY() + (getHeight() / 2.0f), batch.getPackedColor(), (this.regionU2 + this.regionU) / 2.0f, (this.regionV + this.regionV2) / 2.0f, getX() + (getWidth() / 2.0f) + ((getWidth() / 2.0f) * w13), getY() + getHeight(), batch.getPackedColor(), ((this.regionU2 + this.regionU) / 2.0f) + ((this.UWidth / 2.0f) * w13), this.regionV, getX() + getWidth(), getY() + getHeight(), batch.getPackedColor(), this.regionU2, this.regionV, getX() + getWidth(), getY() + (getHeight() / 2.0f), batch.getPackedColor(), this.regionU2, (this.regionV + this.regionV2) / 2.0f}, 0, 20);
            }
            batch.setColor(oldcolor);
        }
    }
}

实现方式二:


public class CircleProgress extends Actor {
    private TextureRegion texture;//裁剪画的纹理
    private TextureRegion point;
    private Vector2 center;
    private Vector2 centerTop;//从上面中间开始
    private Vector2 leftTop;
    private Vector2 leftBottom;
    private Vector2 rightBottom;
    private Vector2 rightTop;
    private Vector2 progressPoint;
    private float[] fv;//裁剪画图使用的点阵{point1.x,point1.y,point2.x,point2.y  ......}
    private Vector2 intersectPoint;//当前切割在边上的点
    private float percent = 0;
    //当前正在切割的位置
    private IntersectAt intersectAt;
    private boolean revert = false;
    private float radius;
    private float targetPercent;
    private float speed = 1;
    private ProgressListener listener;
    private boolean start = false;

    //当前切割位置的枚举
    public enum IntersectAt {
        NONE, TOP, BOTTOM, LEFT, RIGHT;
    }

    //前两个参数边框,
    public CircleProgress(TextureRegion ground, TextureRegion point, float radius) {
        setName("circle");
        setSize(ground.getRegionWidth(), ground.getRegionHeight());
        this.texture = ground;
        this.point = point;
        this.radius = radius;

        //计算各点内部坐标
        center = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
        centerTop = new Vector2(this.getWidth() / 2, this.getHeight());
        leftTop = new Vector2(0, this.getHeight());
        leftBottom = new Vector2(0, 0);
        rightBottom = new Vector2(this.getWidth(), 0);
        rightTop = new Vector2(this.getWidth(), this.getHeight());
        progressPoint = new Vector2(this.getWidth() / 2, this.getHeight() / 2);

    }

    public void setRevert(boolean revert) {
        this.revert = revert;
    }

    //计算切线的最远点
    private Vector2 IntersectPoint(Vector2 line) {
        Vector2 v = new Vector2();
        boolean isIntersect;

        //check top
        isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, v);//切割线和上边的交点v

        //check bottom
        if (isIntersect) {
            intersectAt = IntersectAt.TOP;
            return v;
        } else isIntersect = Intersector.intersectSegments(leftBottom, rightBottom, center, line, v);

        //check left
        if (isIntersect) {
            intersectAt = IntersectAt.BOTTOM;
            return v;
        } else isIntersect = Intersector.intersectSegments(leftTop, leftBottom, center, line, v);

        //check bottom
        if (isIntersect) {
            intersectAt = IntersectAt.LEFT;
            return v;
        } else isIntersect = Intersector.intersectSegments(rightTop, rightBottom, center, line, v);

        if (isIntersect) {
            intersectAt = IntersectAt.RIGHT;
            return v;
        } else {
            intersectAt = IntersectAt.NONE;
            return null;
        }
    }


    public void setTargetPercent(float targetPercent,boolean now,float speed,ProgressListener listener) {
        this.targetPercent = targetPercent;
        this.listener = listener;
        this.speed = speed;
        if(now){
            setPercentage(targetPercent);
            if(listener!=null) {
                listener.end();
            }
        }else{
            start = true;
        }
    }

    public void setStop(boolean stop) {
        this.stop = stop;
    }

    private boolean stop = false;
    @Override
    public void act(float delta) {
        super.act(delta);
        if (!stop) {
            if (start) {
                if (speed > 0) {
                    if (percent + delta * 10.0F < targetPercent) {
//                    setPercentage(percent+ speed);
                        setPercentage(percent + 10.0F * delta);
                    } else {
                        setPercentage(targetPercent);
//                    setPercentage(targetPercent);
                        if (listener != null) {
                            start = false;
                            listener.end();
                        }
                    }
                } else {
                    if (percent + speed > targetPercent) {
                        setPercentage(percent + speed);
                    } else {
                        setPercentage(targetPercent);
                        if (listener != null) {
                            start = false;
                            listener.end();
                        }
                    }
                }
            }
        }
    }

    //设置百分比,顺时针
    public void setPercentage(float percent) {

        if (percent >= 100) {
            percent = 100F;
        }
        this.percent = percent;
        float angle = convertToRadians(90); //percent = 0 => angle = -90
        angle -= convertToRadians(percent * 360 / 100);

        float len = this.getWidth() > this.getHeight() ? this.getWidth() : this.getHeight();
        float dy = (float) (Math.sin(angle) * len);
        float dx = (float) (Math.cos(angle) * len);
        Vector2 line = new Vector2(center.x + dx, center.y + dy);
        intersectPoint = IntersectPoint(line);
        float l = intersectPoint.dst(center.x, center.y);
        float sy = 2 * l / getHeight();
        if (intersectAt == IntersectAt.TOP) {
            if (intersectPoint.x >= this.getWidth() / 2) {
                fv = new float[]{
                        center.x,
                        center.y,
                        centerTop.x,
                        centerTop.y,
//                        leftTop.x,
//                        leftTop.y,
//                        leftBottom.x,
//                        leftBottom.y,
//                        rightBottom.x,
//                        rightBottom.y,
//                        rightTop.x,
//                        rightTop.y,
                        intersectPoint.x,
                        intersectPoint.y
                };
            } else {
                fv = new float[]{ // cắt bên trái cạnh
                        center.x,
                        center.y,
                        centerTop.x,
                        centerTop.y,
                        rightTop.x,
                        rightTop.y,
                        rightBottom.x,
                        rightBottom.y,
                        leftBottom.x,
                        leftBottom.y,
                        leftTop.x,
                        leftTop.y,
                        intersectPoint.x,
                        intersectPoint.y
                };
            }
        } else if (intersectAt == IntersectAt.BOTTOM) {
            fv = new float[]{
                    center.x,
                    center.y,
                    centerTop.x,
                    centerTop.y,
                    rightTop.x,
                    rightTop.y,
                    rightBottom.x,
                    rightBottom.y,
                    intersectPoint.x,
                    intersectPoint.y
            };

        } else if (intersectAt == IntersectAt.LEFT) {
            fv = new float[]{
                    center.x,
                    center.y,
                    centerTop.x,
                    centerTop.y,
                    rightTop.x,
                    rightTop.y,
                    rightBottom.x,
                    rightBottom.y,
                    leftBottom.x,
                    leftBottom.y,
                    intersectPoint.x,
                    intersectPoint.y
            };

        } else if (intersectAt == IntersectAt.RIGHT) {
            fv = new float[]{
                    center.x,
                    center.y,
                    centerTop.x,
                    centerTop.y,
                    rightTop.x,
                    rightTop.y,
//                    leftBottom.x,
//                    leftBottom.y,
//                    rightBottom.x,
//                    rightBottom.y,
                    intersectPoint.x,
                    intersectPoint.y
            };
        } else {
            fv = null;
        }
        EarClippingTriangulator e = new EarClippingTriangulator();
        ShortArray sv = e.computeTriangles(fv);
        PolygonRegion polyReg = new PolygonRegion(texture, fv, sv.toArray());
        //创建 polySprite.
        if (poly == null) {
            poly = new PolygonSprite(polyReg);
        } else {
            poly.setRegion(polyReg);
        }
        if (revert) {
            poly.setScale(-1, 1);
        } else {
            poly.setScale(1, 1);
        }


    }

    PolygonSprite poly;

    //重新绘制函数
    @Override
    public void draw(Batch batch, float parentAlpha) {
//        //裁剪

        //创建 polygonRegion.

        //(position, origin, rotation, color)
        //设置中心点
        if (percent <= 0) {

        } else if (percent >= 99.9F) {
            Color batchColor = batch.getColor();
            batch.setColor(getColor());
            batch.draw(texture, getX(), getY());
            batch.setColor(batchColor);
        } else if (poly != null) {
            poly.setOrigin(this.getOriginX(), this.getOriginY());
            //设置位置
            if (revert) {
                poly.setPosition(this.getX() + centerTop.x * 2, this.getY());
            } else {
                poly.setPosition(this.getX(), this.getY());
            }
            poly.setRotation(this.getRotation());
            poly.setColor(this.getColor());
            //绘制

            float an = percent / 100 * 360;
            float pointX = (float) (radius * Math.sin(Math.PI * an / 180.0));
            float pointY = (float) (radius * Math.cos(Math.PI * an / 180.0));
            if(revert){
                batch.draw(point, getX() + getWidth() / 2 - pointX + -point.getRegionWidth() / 2, getY() + getHeight() / 2 + pointY - point.getRegionHeight() / 2);
                batch.draw(point, getX() + getWidth() / 2 + -point.getRegionWidth() / 2, getY() + getHeight() / 2 + radius - point.getRegionHeight() / 2);
            }else {
                batch.draw(point, getX() + getWidth() / 2 + pointX + -point.getRegionWidth() / 2, getY() + getHeight() / 2 + pointY - point.getRegionHeight() / 2);
                batch.draw(point, getX() + getWidth() / 2 + -point.getRegionWidth() / 2, getY() + getHeight() / 2 + radius - point.getRegionHeight() / 2);
            }
            poly.draw((PolygonSpriteBatch) batch);
//            batch.draw(point);
//            if (starPoint!=null){
//                starPoint.setPosition(
//                        (float) (progress.getX(Align.center)+r*Math.sin(Math.PI*0/180.0)),
//                        (float) (progress.getY(Align.center)+r*Math.cos(Math.PI*0/180.0)),
//                        Align.center);
//            }
        }
    }

    float convertToDegrees(float angleInRadians) {
        float angleInDegrees = angleInRadians * 57.2957795f;
        return angleInDegrees;
    }

    float convertToRadians(float angleInDegrees) {
        float angleInRadians = angleInDegrees * 0.0174532925f;
        return angleInRadians;
    }

    public interface ProgressListener{
        void end();
    }
}
上一篇 下一篇

猜你喜欢

热点阅读