Search code examples
javabufferedimagegraphics2d

How to draw a sector of a BufferedImage?


I'm making a game with a mouse cursor, and I'd like to represent the health by overlaying the cursor with a green version of the image, but only a geometric sector of it corresponding to the health percentage. Solutions from posts like these: Drawing slices of a circle in java? & How to draw portions of circles based on percentages in Graphics2D? are pretty much what I want to do, but with a BufferedImage as opposed to a solid color fill.

    //Unfortunately all this does is cause nothing to draw, but commenting this out allows the overlay image to draw
    Arc2D.Double clip = new Arc2D.Double(Arc2D.PIE);
    double healthAngle = Math.toRadians((((Double)data.get("health")).doubleValue() * 360.0 / 100.0) - 270.0);
    clip.setAngles(0, -1, Math.cos(healthAngle), Math.sin(healthAngle));
    System.out.println(Math.cos(healthAngle) + " " + Math.sin(healthAngle));
    g.setClip(clip);

In short, how do I draw a sector of a BufferedImage given any angle?


Solution

  • If you read the API docs for setClip(Shape) you'll see that the only shape that is guaranteed to work, is a rectangle. So, setting the clip probably won't work.

    However, there are other options. The most obvious is probably to use a TexturePaint to fill your arc with the BufferedImage. Something like:

    TexturePaint healthTexture = new TexturePaint(healthImg, new Rectangle(x, y, w, h));
    g.setPaint(healthTexture);
    g.fill(arc); // "arc" is same as you used for "clip" above
    

    Another option is to first draw the arc in solid color, over a transparent background, then paint the image over that, using the SRC_IN Porter-Duff mode. Something like:

    g.setPaint(Color.WHITE);
    g.fill(arc); // arc is same as your clip
    g.setComposite(AlphaComposite.SrcIn); // (default is SrcOver)
    g.drawImage(x, y, healthImg, null);