2017-04-20 168 views
2

我想创建一个cricle进度条,它看起来像使用libgdx库的this。现在,我创建了简单的水平进度条,使用不同的图像作为图层叠加自身,其中一个图层调整大小以模拟进度。我发现this的例子,如何绘制圆形进度条,但我不明白如何使用这个实现,我该如何处理它。构造器中的textureRegion是进度指示器吗?而我找不到负责设定实际进度的方法。在libGDX中实现cricle进度条

编辑:我做了我的解决方案基本this implementation。我把3层叠加在自己身上,每当中间层滑动的时候显示进度。但我有一个问题:每当我尝试调整我的ProgressCircle实例时,它会向下移动到背景层下面。

public class ProgressCircle extends Image { 

    public enum IntersectAt { 
     NONE, TOP, BOTTOM, LEFT, RIGHT; 
    } 

    TextureRegion texture; 

    PolygonSpriteBatch polyBatch; 

    Vector2 center; 
    Vector2 centerTop; 
    Vector2 leftTop; 
    Vector2 leftBottom; 
    Vector2 rightBottom; 
    Vector2 rightTop; 
    Vector2 progressPoint; 

    float[] fv; 


    IntersectAt intersectAt; 
    private float PROGRESS_WIDTH=0f; 
    private float PROGRESS_HEIGHT=0f; 
    private float posX,posY; 

    public ProgressCircle(TextureRegion region, PolygonSpriteBatch polyBatch,float width,float height,float posX,float posY) { 
     super(region); 
     PROGRESS_WIDTH=width; 
     PROGRESS_HEIGHT=height; 
     this.posX=posX; 
     this.posY=posY; 

     this.texture = region; 
     this.polyBatch = polyBatch; 

     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); 

     setPercentage(0); 

    } 

    private Vector2 IntersectPoint(Vector2 line) { 
     Vector2 v = new Vector2(); 
     boolean isIntersect; 

     //check top 
     isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, 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 setPercentage(float percent) { 
     //100 % = 360 degree 

     float angle = convertToRadians(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); 

     Vector2 v = IntersectPoint(line); 

     if (intersectAt == IntersectAt.TOP) { 
      if (v.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, 
         v.x, 
         v.y 
       }; 
      } else { 
       fv = new float[]{ 
         center.x, 
         center.y, 
         centerTop.x, 
         centerTop.y, 
         v.x, 
         v.y 
       }; 

      } 
     } else if (intersectAt == IntersectAt.BOTTOM) { 
      fv = new float[]{ 
        center.x, 
        center.y, 
        centerTop.x, 
        centerTop.y, 
        leftTop.x, 
        leftTop.y, 
        leftBottom.x, 
        leftBottom.y, 
        v.x, 
        v.y 
      }; 

     } else if (intersectAt == IntersectAt.LEFT) { 
      fv = new float[]{ 
        center.x, 
        center.y, 
        centerTop.x, 
        centerTop.y, 
        leftTop.x, 
        leftTop.y, 
        v.x, 
        v.y 
      }; 

     } else if (intersectAt == IntersectAt.RIGHT) { 
      fv = new float[]{ 
        center.x, 
        center.y, 
        centerTop.x, 
        centerTop.y, 
        leftTop.x, 
        leftTop.y, 
        leftBottom.x, 
        leftBottom.y, 
        rightBottom.x, 
        rightBottom.y, 
        v.x, 
        v.y 
      }; 

     } else // if (intersectAt == IntersectAt.NONE) 
     { 

      fv = null; 
     } 


    } 


    @Override 
    public void draw(Batch batch, float parentAlpha) { 
     if (fv == null) return; 
     batch.end(); 
     drawMe(); 
     batch.begin(); 
    } 


    public void drawMe() { 

     EarClippingTriangulator e = new EarClippingTriangulator(); 
     ShortArray sv = e.computeTriangles(fv); 

     PolygonRegion polyReg = new PolygonRegion(texture, fv, sv.toArray()); 

     PolygonSprite poly = new PolygonSprite(polyReg); 
     poly.setSize(PROGRESS_WIDTH,PROGRESS_HEIGHT); 
     poly.setPosition(posX,posY); 
     poly.setOrigin(poly.getOriginX(), poly.getOriginY()); 
     poly.setRotation(this.getRotation()); 
     poly.setColor(Color.GREEN); 

     polyBatch.begin(); 
     poly.draw(polyBatch); 
     polyBatch.end(); 
    } 


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

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

和我的初始化函数:

ProgressCircle sprite; 

private void initCircleProgress() { 

    Group group = new Group(); 
    Image downBackground = new Image(atlas.findRegion("progressBackground")); 
    downBackground.setColor(Color.BLUE); 
    downBackground.setSize(USER_SCREEN_SIZE_WIDTH/5,USER_SCREEN_SIZE_WIDTH/5); 
    downBackground.setPosition(10,USER_SCREEN_SIZE_HEIGHT-(2*downBackground.getHeight()+20)); 

    sprite = new ProgressCircle(atlas.findRegion("progressBackground"), pbatch, 
      downBackground.getWidth(),downBackground.getHeight(),downBackground.getX(),downBackground.getY()); 
    sprite.setSize(downBackground.getWidth(),downBackground.getHeight()); 
    sprite.setSize(downBackground.getX(),downBackground.getY()); 
    Image label = new Image(atlas.findRegion("progressBackground")); 
    label.setSize(downBackground.getWidth()*0.8f,downBackground.getHeight()*0.8f); 
    label.setPosition(downBackground.getX()+(downBackground.getWidth()-label.getWidth())/2, 
      downBackground.getY()+(downBackground.getHeight()-label.getHeight())/2); 
    label.setColor(Color.WHITE); 
    group.addActor(downBackground); 
    group.addActor(sprite); 
    group.addActor(label); 
    group.setPosition(10,GAME_SIZE_HEIGHT-(group.getHeight()+20)); 
    stage.addActor(group); 

} 

enter image description here

回答

0

你需要一个圆形梯度mask出所需的部件。

enter image description here

随时间递增的掩蔽值将导致循环运动。

正如您在link to masking中看到的,有几种方法可以实现此目的。模板缓冲区将是一个不错的选择,但会导致锯齿边缘。编写你自己的着色器将是完美的,但有点难if you never wrote a shader。您还可以尝试解析两个像素映射,并决定在两个像素映射中循环时绘制哪些像素。如果遮罩图像和源代码具有相同的纹理空间,则可以在一个循环中执行此操作,所以它不会比着色器慢得多,而且适合您的任何方法都是很好的解决方案,您可以随后进行优化。