1

Here's my problem- I'm trying to draw a circular part of a single image.

I'm doing some work on a top-down dungeon crawler sort of game, and I'm attempting to make a light radius around the player. The floor is a single image, and I need to draw only a small, circular part of it. I've been looking at this method:

drawImage(Image img,
          int dx1, 
          int dy1,
          int dx2,
          int dy2,
          int sx1,
          int sy1,
          int sx2,
          int sy2,
          Color bgcolor, 
          ImageObserver observer) 

But, that looks like it would only draw a square subsection. Does anyone happen to know an easier method than drawing tons of little squares to give the illusion of a circle?

Thanks

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373

3 Answers3

2

You can do this with the setClip() method in Graphics.

It needs some other work, but:

import java.awt.Graphics;
import java.awt.geom.QuadCurve2D;
//...

  g.setClip(new QuadCurve()); // Set the bounding curve for the image.
  g.drawImage(...);

As I said, it needs more work, meaning the QuadCurve2D object might need to be defined differently, but you can check the doc for that.

simon04
  • 3,054
  • 29
  • 25
Jon Egeland
  • 12,470
  • 8
  • 47
  • 62
  • 1
    I'll look into this. Thanks so much. Do you think I could substitute Ellipse2D instead of QuadCurve? –  Mar 13 '12 at 02:50
  • I'm not sure, I didn't really look into it that much. If `Ellipse2D` implements `Shape` then it will work. – Jon Egeland Mar 13 '12 at 02:51
  • Alright, I'll go play around with it for an hour or two. Thanks! –  Mar 13 '12 at 02:53
  • Actually, wait. All the drawImage()'s that I see want x,y locations, which implies a square to me. How exactly do I get the setClip info into drawImage? Sorry if that seems thick, but I don't see any return info from the setClip that is useful. –  Mar 13 '12 at 02:56
  • `setClip` applies to the `Graphics` object - in my example, `g`. That means whenever you draw something, the clip will automatically be applied. That being said, you should clear the clip after your done with it as to avoid messing up other code. – Jon Egeland Mar 13 '12 at 02:58
  • That did it. Thank you sir, you are both a gentleman and a scholar. –  Mar 13 '12 at 03:09
  • 1
    Or make a copy Graphics object, apply the clip to it, and then dispose of the Graphic when done with it. – Hovercraft Full Of Eels Mar 13 '12 at 03:09
1

The neatest effect for a light radius would be to use an overlay with a gradient in its alpha channel.

Something like this:

// do this once during setup
overlay = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGBA);
for (int x = 0; x < width; ++x)
{
    for (int y = 0; y < height; ++y)
    {
        double range = 100;
        double distance = Math.sqrt(Math.pow(x - width / 2, 2) + Math.pow(y - height / 2, 2));
        int value = Math.max(100, (int)Math.round(255 - 100 * distance / range));
        overlay.setRGB(x, y, new Color(0, 0, 0, value));
    }
}
....
// do this every frame
gfx.drawImage(overlay, 0, 0, null);

I did not compile this so it's probably full of errors!

If you want some "flicker" in it you can generate several maps, and add some noise to the alpha values. Or even tune the colors so you get warmer light.

Wouter Lievens
  • 4,019
  • 5
  • 41
  • 66
0

This isn't a great solution, but what if you drew the entire floor, then a black image with a transparent hole in its center?

amc6
  • 273
  • 3
  • 13
  • I've been kind of thinking about that, but I'd like to find another way if at all possible. Plus, unless I just made that image in Photoshop, it still leaves me with the circular hole problem. I'd like to do it in Java, preferably. –  Mar 13 '12 at 02:49