Libgdx 圆形进度条的实现

Libgdx 圆形进度条的实现

(待完善)

先上效果图:

Libgdx 圆形进度条的实现_第1张图片

思路:

1.准备两张图

Libgdx 圆形进度条的实现_第2张图片 

纹理1

Libgdx 圆形进度条的实现_第3张图片

纹理2

纹理2覆盖在纹理1上,纹理2的圆环透明

2.采用Mesh进行绘制纹理1

对于Mesh的使用在这不再讲解,实际上在图形的绘制都是由一个一个三角形绘制而来,圆形,矩形,多边形都能切割成三角形

对纹理1,如下图,我们取9个顶点坐标,使用网格(Mesh)进行绘制

Libgdx 圆形进度条的实现_第4张图片

根据进度使用Mesh绘制1 、2、 ~ last组合的三角形

Libgdx 圆形进度条的实现_第5张图片Libgdx 圆形进度条的实现_第6张图片

初始化个顶点数据,颜色值默认为0

代码如下:

        /**
         * 初始话顶点位置 与 纹理坐标
         */
        for (int i = 0; i < 9; i++) {
            vertices[i * 5 + 0] = (vertices[i * 5] + (width / 2.0f));
            vertices[i * 5 + 1] = (vertices[i * 5 + 1] + (height / 2.0f));
            Vector2 uv = getUV(region, vertices[i * 5], vertices[i * 5 + 1]);
            vertices[i * 5 + 3] = uv.x;
            vertices[i * 5 + 4] = uv.y;
        }

Mesh的顶点数据的构成:顶点坐标(x,y) + 颜色(float) + 纹理坐标(x,y)

1: 顶点坐标 : ( 51.0 , 51.0 ), color:0.0, 纹理坐标:( 0.5 , 0.5)

2: 顶点坐标 : ( 51.0 , 102.0 ), color:0.0, 纹理坐标:( 0.5 , 0.0)

3: 顶点坐标 : ( 102.0 , 102.0 ), color:0.0, 纹理坐标:( 1.0 , 0.0)

4: 顶点坐标 : ( 102.0 , 51.0 ), color:0.0, 纹理坐标:( 1.0 , 0.5)

5: 顶点坐标 : ( 102.0 , 0.0 ), color:0.0, 纹理坐标:( 1.0 , 1.0)

6: 顶点坐标 : ( 51.0 , 0.0 ), color:0.0, 纹理坐标:( 0.5 , 1.0)

7: 顶点坐标 : ( 0.0 , 0.0 ), color:0.0, 纹理坐标:( 0.0 , 1.0)

8: 顶点坐标 : ( 0.0 , 51.0 ), color:0.0, 纹理坐标:( 0.0 , 0.5)

9: 顶点坐标 : ( 0.0 , 102.0 ), color:0.0, 纹理坐标:( 0.0 , 0.0)

纹理1  w 102.0 X h102.0



package com.whs.demo.progress;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;

public class CircularProgress
    extends Actor {

    // 位置   - (x0, y0)
    public static final int POSITION_COMPONENTS = 2;
    // 颜色   - (r, g, b, a)
    public static final int COLOR_COMPONENTS = 4;
    // 纹理坐标    - (x1,y1)
    public static final int TEXCOORD_COMPONENTS = 2;
    // 定义最大10组数据  位置 + 颜色 + 纹理坐标
    private static final int MAX_VERTICES = 10;
    // COMPONENTS
    private static final int TOTAL_COMPONENTS = 5; 
    
    private static final int MAX_INDICES  =  0;
  
    protected int idx = 0;
    
    private Vector2 last;
    private Mesh mesh;
    private TextureRegion region;
    private ShaderProgram shader;
    private float percent;
    /**
     *  顶点数据,组合为(位置坐标 + 颜色 + 纹理坐标 ),颜色以float类型表示
     * x0, y0, color,x1,y1
     * x0, y0, color,x1,y1
     * x0, y0, color,x1,y1
     * .....
     */
    private float[] vertices;
    
    

    public CircularProgress(TextureRegion region) {
        this.region = region;

        /**
         *  使用默认的shader
         *  一般不指定ShaderProgram,我们使用SpriteBatch的时候都是使用默认的shader
         */
        this.shader = SpriteBatch.createDefaultShader();
        
        // 设置顶点数据类型为数组类型
        Mesh.VertexDataType vertexDataType = Mesh.VertexDataType.VertexArray;
        
        /**
         * 只需要处理 :顶点坐标、颜色、纹理坐标 
         */
        VertexAttribute[] vertexAttributes = new VertexAttribute[3];
        vertexAttributes[0] = new VertexAttribute(Usage.Position, POSITION_COMPONENTS, "a_position");
        vertexAttributes[1] = new VertexAttribute(Usage.ColorPacked, COLOR_COMPONENTS, "a_color");
        vertexAttributes[2] = new VertexAttribute(Usage.TextureCoordinates, TEXCOORD_COMPONENTS, "a_texCoord0");
        
        this.mesh = new Mesh(vertexDataType, false, MAX_VERTICES, MAX_INDICES, vertexAttributes);
        float width = region.getRegionWidth();
        float height = region.getRegionHeight();
        
        /**
         * 初始化顶点数据
         */
        vertices = new float[MAX_VERTICES  * TOTAL_COMPONENTS];

        int idx = 0; 
        vertices[(idx++)] = 0;
        vertices[(idx++)] = 0;

        idx = idx + 3; 
        vertices[(idx++)] = 0;
        vertices[(idx++)] = (height / 2.0f);

        idx = idx + 3;
        vertices[(idx++)] = (width / 2.0f);
        vertices[(idx++)] = (height / 2.0f);

        idx = idx + 3;
        vertices[(idx++)] = (width / 2.0f);
        vertices[(idx++)] = 0;

        idx = idx + 3;
        vertices[(idx++)] = (width / 2.0f);
        vertices[(idx++)] = (-height / 2.0f);

        idx = idx + 3;
        vertices[(idx++)] = 0;
        vertices[(idx++)] = (-height / 2.0f);

        idx = idx + 3; 
        vertices[(idx++)] = (-width / 2.0f);
        vertices[(idx++)] = (-height / 2.0f);

        idx = idx + 3; 
        vertices[(idx++)] = (-width / 2.0f);
        vertices[(idx++)] = 0;

        idx = idx + 3; 
        vertices[(idx++)] = (-width / 2.0f);
        vertices[(idx++)] = (height / 2.0f);
       
        /**
         * 初始话顶点位置 与 纹理坐标
         */
        for (int i = 0; i < 9; i++) {
            vertices[i * 5 + 0] = (vertices[i * 5] + (width / 2.0f));
            vertices[i * 5 + 1] = (vertices[i * 5 + 1] + (height / 2.0f));
            Vector2 uv = getUV(region, vertices[i * 5], vertices[i * 5 + 1]);
            vertices[i * 5 + 3] = uv.x;
            vertices[i * 5 + 4] = uv.y;
            
        }
        
        
    }
    
 

    /**
     * 计算纹理坐标
     * @author whs  
     * @date 2015-11-25 下午4:24:03
     * @param region
     * @param x
     * @param y
     * @return
     * @Description:
     */
    private Vector2 getUV(TextureRegion region, float x, float y) {
        float u = region.getU();
        float v = region.getV();
        float u2 = region.getU2();
        float v2 = region.getV2();
        return new Vector2(u + x / region.getRegionWidth() * (u2 - u), v2 - y / region.getRegionHeight() * (v2 - v));
    }

    public void draw(Batch batch, float parentAlpha) {
        Gdx.gl.glEnable(GL20.GL_BLEND);
        Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        Gdx.gl.glDepthMask(false);
        int n = 3 + (int) (8F * this.percent);
        if (n > 10) {
            n = 10;
        }
        float vertices[] = new float[n * 5];
        float x = getX();
        float y = getY();
        float fColor = getColor().toFloatBits();
        int idx = 0;;

        for (int j = 0; j < n - 1; j++) {
            vertices[0 + j * 5] = x + this.vertices[j * 5];
            vertices[1 + j * 5] = y + this.vertices[1 + j * 5];
            vertices[2 + j * 5] = fColor;
            vertices[3 + j * 5] = this.vertices[3 + j * 5];
            vertices[4 + j * 5] = this.vertices[4 + j * 5];
            idx += 5;
        }
        if (this.last != null) {
            vertices[idx + 0] = x + this.last.x;
            vertices[idx + 1] = y + this.last.y;
            vertices[idx + 2] = fColor;
            Vector2 uv = getUV(this.region, this.last.x, this.last.y);
            vertices[idx + 3] = uv.x;
            vertices[idx + 4] = uv.y;

        }
        this.region.getTexture().bind();
        this.mesh.setVertices(vertices, 0, vertices.length);
        this.mesh.render(this.shader, GL20.GL_TRIANGLE_FAN, 0, n);
        Gdx.gl.glDepthMask(true);

    }

    public void setPercent(float percent) {
        if (percent < 0.0F) {
            percent = 0.0F;
        } else if (percent >= 1.0F) {
            percent = 1.0F;
        }
        int i = 1;
        int k;
        this.percent =  percent;
        int n =  (int) (8F * this.percent);
        float pp = ( this.percent - 0.125F * n) / 0.125F;
        if (n + 1 > 8) {
            k = i;
        } else {
            k = n + 1;
        }
        if (k + 1 <= 8) {
            i = k + 1;
        }
        last = new Vector2(vertices[k * 5] + pp * (vertices[i * 5] - vertices[k * 5]), vertices[1 + k * 5] + pp
            * (vertices[1 + i * 5] - vertices[1 + k * 5]));
    }
}



Libgdx 圆形进度条的实现_第7张图片


Libgdx 圆形进度条的实现_第8张图片




你可能感兴趣的:(归档)