2

I am coding the board game Risk in java for a project in school. I need to make each of the territories a separate button. I have each of the territories separated into different pictures with transparent backgrounds. I understand 2D java buttons are rectangle-oriented, so I might have to use alpha values, since I the backgrounds of each territory have been given a transparent background.

If I do that, two problems become present:

  1. I don't know if the transparent area of the button is being pressed.
  2. The buttons overlap because of their innate rectangular shape, and I need only the button which contains the non-transparent pixel that was clicked to be initiated.

Or is there altogether a more efficient way to approach coding the game? Any help is welcome, as it is much needed. I found a java version of the board game online, but I cannot understand it. (It's labeled domination, but is actually Risk. Link to the map|| The link to the game I found online

Jacob Schoen
  • 14,034
  • 15
  • 82
  • 102
user1272300
  • 23
  • 1
  • 3

2 Answers2

4

Here is something I made that you can go ahead and use that senses motion only on regions without transparency.

IMAGEBUTTON.java works just like an JButton except you give it an imageIcon and it sense the alpha provides class that

Use setMinimumDetectionAlpha() in case if you have any shadows coming of you png.

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;

@SuppressWarnings("serial")
public class ImageButton extends javax.swing.JButton implements MouseListener{

private MouseListener mouseListener = null;
private BufferedImage bufferedImage;
private int minAlpha = 0x0;
private boolean userMouseListener = false;

public ImageButton(ImageIcon ic){
    super();
    setPreferredSize(new Dimension(ic.getIconWidth(), ic.getIconHeight()));
    setImage(ic);
    addMouseListener(this);
}
protected BufferedImage imageIconToBufferedImage(ImageIcon a){
    BufferedImage bi = new BufferedImage(a.getIconWidth(), a.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = (Graphics2D) bi.getGraphics();
    g2d.drawImage(a.getImage(), 0,0,null);
    g2d.dispose();
    return bi;
}
public void setImage(ImageIcon ic){
    bufferedImage = imageIconToBufferedImage(ic);
    repaint();
}
protected void paintComponent(Graphics g){
    Graphics2D g2d = (Graphics2D) g;
    RenderingHints _rh = g2d.getRenderingHints();
    g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.drawImage(bufferedImage, 0, 0, null);
    g2d.setRenderingHints(_rh);
}
protected void setMinimumDetectionAlpha(int alpha){
    minAlpha = alpha == 0 ? 1 : alpha;
    minAlpha =  minAlpha % 0x000000FF << 0x00000010;
}
protected void processMouseEvent(MouseEvent e) {
    if(checkInBounds(e.getX(), e.getY())){
        switch(e.getID()){
            case MouseEvent.MOUSE_CLICKED:  mouseListener.mouseClicked(e);      break;
            case MouseEvent.MOUSE_ENTERED:  mouseListener.mouseEntered(e);      break;
            case MouseEvent.MOUSE_EXITED:   mouseListener.mouseExited(e);       break;
            case MouseEvent.MOUSE_PRESSED:  mouseListener.mousePressed(e);      break;
            case MouseEvent.MOUSE_RELEASED: mouseListener.mouseReleased(e);     break;
        }           
        e.consume();            
    }
}
public void addMouseListener(MouseListener a){
    if(!userMouseListener)
        super.addMouseListener(a);
    else
        mouseListener = a;
    userMouseListener = true;       
}
protected boolean checkInBounds(int x, int y){
    try{        
        if((bufferedImage.getRGB(x, y) & 0xFF000000)>>>4 >= (minAlpha > 0 ? minAlpha : 0x08800000))
            return true;
        else
            throw new Exception();
    }catch(Exception e){
        return false;
    }
}
@Override
public void mouseClicked(MouseEvent e)  {       processMouseEvent(e);       }
@Override
public void mouseEntered(MouseEvent e)  {       processMouseEvent(e);       }
@Override
public void mouseExited(MouseEvent e)   {       processMouseEvent(e);       }
@Override
public void mousePressed(MouseEvent e)  {       processMouseEvent(e);       }
@Override
public void mouseReleased(MouseEvent e) {       processMouseEvent(e);   }
}

you can just go ahead and use it like this

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;


public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
    JFrame jmb = new JFrame();
    ImageButton ib = new ImageButton(new ImageIcon("res/buttonImage.png"));
    ib.setMinimumDetectionAlpha(0);
    ib.addMouseListener(new MouseListener(){

        @Override
        public void mouseClicked(MouseEvent e) {
            System.out.println("eventFired");       

        }

        @Override
        public void mouseEntered(MouseEvent e) {
            System.out.println("eventFired");       

        }

        @Override
        public void mouseExited(MouseEvent e) {
            System.out.println("eventFired");       

        }

        @Override
        public void mousePressed(MouseEvent e) {
            System.out.println("eventFired");       

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            System.out.println("eventFired");       

        }

    });
    jmb.add(ib);
    jmb.pack();
    jmb.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jmb.show();
}

}

the image used was something like this

buttonImage.png

I hope this helps you :D

Mathew Kurian
  • 5,949
  • 5
  • 46
  • 73
3

Can you avoid using multiple Buttons, and just add a MouseListener on a custom-drawn panel?

My hesitation is that I doubt even with transparent buttons you'd get the behavior you want when they overlap. Might find some fancy point-in-polygon algorithm helpful when handling the click.

Rob I
  • 5,627
  • 2
  • 21
  • 28
  • 1
    [`Polygon`](http://docs.oracle.com/javase/7/docs/api/java/awt/Polygon.html) has a suitable `contains()` implementation. – trashgod Mar 15 '12 at 22:07
  • Rob, how do I make a custom-drawn panel? I'm sorry if I sound dumb, but I'm quite new to this. Thank you for your help. – user1272300 Mar 16 '12 at 06:04
  • Create a new class that extends `JPanel`, and add an override for the `paintComponent(Graphics)` method. – Rob I Mar 16 '12 at 13:52