Clickable areas on image

Hi. I'm creating a role playing game where the user can click on certain parts of an image to go somewhere or pickup something up. There's a few strategies to accomplish this, but I'm up against the wall with all of them, being a little bit new to swing/awt.

I'm using complex shapes for the clickable areas (not simple rectangular/elliptical areas), probably best represented using images that are kind of overlaid on the viewed image.

1) Overlay an image with very low transparency level. But Java doesn't immediately recognise transparency in GIFs. How do you do that? Also if you paint an image with a semi-transparent colour, can you display that in Java? Or even, how can you change an image's transparency level?

or 2) Hold an image in memory but not actually display it, so that as you track the mouse pointer across the screen you check the corresponding colour in the other image and see if there is a coloured region (and change the cursor to a hand for example). I got really stuck trying to figure out how to get a pixel colour for given x/y coords in swing/awt. (yes, there's getRGB, but how can you get there from JLabel). Could you help here?

If there is a better way to do any of this, your help would be really appreciated! Eric

[1284 byte] By [Ericheroa] at [2007-11-27 0:32:23]
# 1

hi Erichero,

there are definitely several solutions for your problem.

If you want to use images to define your hit areas, here is what I would do:

I usually do it with PNG images, but htis should work the same with GIFs.

First load your image and in order to speed up the display, make it compatible with you GraphicsConfiguration in a BufferedImage as follow:

BufferedImage im = ImageIO.read(new File("my_image_file_path");

int transparency = im.getColorModel().getTransparency();

BufferedImage copy = gc.createCompatibleImage(im.getWidth(), im.getHeight(), transparency);

Graphics2D g2d = copy.createGraphics();

g2d.drawImage(im, 0, 0, null);

g2d.dispose();

This way you have a BufferedImage ("copy") optimized for display speed. The transparency information is kept in the alpha channel.

You can do this for every hit image at loading time and store them in a list along with the coordinates they should be displayed at.

Then you add a MouseListener to the JComponent you display the images into. In the mouseClicked method, you test the hit as follow:

public void mouseClicked(MouseEvent event)

{

int mouseX = event.getX();

int mouseY = event.getY();

Rectangle dispRect = new Rectangle();

BufferedImage hitImage = null;

for(BufferedImage img : myImageList)

{

//this method should be written in order to retrieve the coordinates where the image img is displayed at.

Point dispCoord = getDispCoord(img);

//set dispRect to be the bounding box of the image a quick test first

dispRect.setRect(dispCoord.x, dispCoord.y, img.getWidth(), img.getHeight());

if(dispRect.contains(mouseX , mouseY ))

{

//if the mouse is within the bounding box of the image, test in details the transparency of the pixel:

if (((img.getRGB(mouseX , mouseY) >> 24) & 0xFF) != 0)

{

//the mouse is over a non fully transparent pixel, so store the hit image and leave the loop.

hitImage = img;

break;

}

}

}

if(hitImage!=null)

{

//perform the action corresponding to the hitImage

}

}

This should solve your hit test problem.

About your question of displaying semi-transparent image:

- if your image is already at the desired transparency level, then just display it with the Graphics2D method: g2d.drawImage(...) at the desired location.

- if you need to set the transparency at disply time, then use the AlphaComposite as follow:

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) 0.5));

g2d.drawImage(...);

O.5 in the code above means you want to display your image at 50% transparency.

Hope this helps.

Let me know if you have issues.

Cheers.

Vince.

blendinga at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...
# 2
Sorry, little mistake in the code.the getRGB should be called with local coords in your img:img.getRGB(mouseX-dispCoord.x , mouseY-dispCoord.y) >> 24) & 0xFF) != 0Let me know whether this match your expectations.Vince.
blendinga at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...
# 3
Thanks for your help! I'll have a chance to sit down with the code again tomorrow and I'll let you know on Friday how I fared.
Ericheroa at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...
# 4

I gave it a shot and got most of it working. I didn't know where you got "gc" from - the GraphicsConfiguration I assume - where do you initialise/retrieve it? So, I only implemented the first image and not the copy.I simply keep the hit image in memory and use solid colours without any transparency. I use mousemoved to track the cursor position and that works 100%.

Ericheroa at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...
# 5

Hi Erichero,

nice to hear this works !

Sorry for the 'gc', forgot the copy/paste...

'gc' is indeed the GraphicsConfiguration obtained as follow:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();

Good luck for the rest of your project !

Cheers.

Vince.

blendinga at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...
# 6
Thanks for your help Vince!
Ericheroa at 2007-7-11 22:37:58 > top of Java-index,Security,Cryptography...