Search code examples
androidkotlinlibgdxpolygonbox2d

LibGDX not showing a smooth rounded polygon


Trying to draw a rounded polygon with the code below, but LibGDX seems to miss some points within the arc.

Anyone can help? Thanks.

enter image description here

class RoundedShape : ShapeRenderer() {

fun roundedRect(x: Float, y: Float, width: Float, height: Float, radius: Float) {
   
    super.rect(x + radius, y + radius, width - 2 * radius, height - 2 * radius)

    super.rect(x + radius, y, width - 2 * radius, radius)
    super.rect(x + width - radius, y + radius, radius, height - 2 * radius)
    super.rect(x + radius, y + height - radius, width - 2 * radius, radius)
    super.rect(x, y + radius, radius, height - 2 * radius)

    super.arc(x + radius, y + radius, radius, 180f, 90f)
    super.arc(x + width - radius, y + radius, radius, 270f, 90f)
    super.arc(x + width - radius, y + height - radius, radius, 0f, 90f)
    super.arc(x + radius, y + height - radius, radius, 90f, 90f)

}
}

Solution

  • Call the overload of the arc() function that has one more argument for number of segments.

    What's going wrong is that it can't estimate a good number of segments if your world space scale is kind of high compared to the screen. When it estimates, it assumes one world space unit is the same size as a pixel on the screen, so in your case it thinks you’re drawing such a small shape that on segment is enough to look like an arc.

    For example:

    val cornerSegments = 8 // adjust until it looks good
    
    super.arc(x + radius, y + radius, radius, 180f, 90f, cornerSegments)
    super.arc(x + width - radius, y + radius, radius, 270f, 90f, cornerSegments)
    super.arc(x + width - radius, y + height - radius, radius, 0f, 90f, cornerSegments)
    super.arc(x + radius, y + height - radius, radius, 90f, 90f, cornerSegments)
    

    Note that drawing shapes this way is kind of expensive. It is having to calculate and draw a lot of triangles to draw those arcs. Not a big deal if there are only a few of these rounded rectangles on screen at once though. But if you have a lot of them (maybe 100 or more drawn simultaneously) and want to support low-end devices you might want to use a pre-rendered sprite instead.