How to add an image into a hexagon in a hexagonal grid?

710 views Asked by At

I have a problem with a hexagonal grid. I found this code you can see below on Internet, so it's not mine. There are two public classes: hexgame which generates the grid and hexmech which draws and fills every single hexagon. What I'd like to do is basically insert an image into a specific hexagon, but I don't know how to code this and in which part of the classes I should put it. Am I thinking the wrong way?

Thank you very much for your help!

Hexgame

package hex;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*; 

public class hexgame
{
private hexgame() {
    initGame();
    createAndShowGUI();
}

final static Color COLOURBACK =  Color.WHITE;
final static Color COLOURCELL =  Color.WHITE;    
final static Color COLOURGRID =  Color.BLACK;    
final static Color COLOURONE = new Color(255,255,255,200);
final static Color COLOURONETXT = Color.BLUE;
final static Color COLOURTWO = new Color(0,0,0,200);
final static Color COLOURTWOTXT = new Color(255,100,255);
final static Color COLOURSAFE = Color.WHITE;
final static Color COLOURDANGEROUS = Color.LIGHT_GRAY;
final static int EMPTY = 0;
final static int UNKNOWN = -1;
final static int SAFE = 1;
final static int DANGEROUS = 2;
final static int CLICKED = 3;
final static int COLUMN_SIZE = 23;
final static int ROW_SIZE = 14;
final static int HEXSIZE = 45;
final static int BORDERS = 15;  

int[][] board = new int[COLUMN_SIZE][ROW_SIZE];

void initGame(){

    hexmech.setXYasVertex(false);
    hexmech.setHeight(HEXSIZE);
    hexmech.setBorders(BORDERS);

    for (int i=0;i<COLUMN_SIZE;i++) {
        for (int j=0;j<ROW_SIZE;j++) {
            board[i][j]=EMPTY;
        }
    }

    board[5][5] = SAFE;
    board[5][6] = SAFE;
    board[5][7] = SAFE;
    board[6][5] = SAFE;
    board [6][6] = SAFE;
    board[4][4] = UNKNOWN;
}

private void createAndShowGUI()
{
    DrawingPanel panel = new DrawingPanel();
    JFrame frame = new JFrame("Hex Testing 4");
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    Container content = frame.getContentPane();
    content.add(panel);
    frame.setSize(825, 630);
    frame.setResizable(true);
    frame.setLocationRelativeTo( null );
    frame.setVisible(true);
}

class DrawingPanel extends JPanel
{   

    public DrawingPanel()
    {   
        setBackground(COLOURBACK);

        MyMouseListener ml = new MyMouseListener(); 
        addMouseListener(ml);
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setFont(new Font("TimesRoman", Font.PLAIN, 15));
        super.paintComponent(g2);

        for (int i=0;i<COLUMN_SIZE;i++) {
            for (int j=0;j<ROW_SIZE;j++) {
                if (board[i][j] != UNKNOWN)
                    hexmech.drawHex(i,j,g2);
            }
        }
        for (int i=0;i<COLUMN_SIZE;i++) {
            for (int j=0;j<ROW_SIZE;j++) {
                if (board[i][j] != UNKNOWN)
                    hexmech.fillHex(i,j,board[i][j],g2);
            }
        }
    }

    class MyMouseListener extends MouseAdapter  { 
        public void mouseClicked(MouseEvent e) { 
            int x = e.getX(); 
            int y = e.getY(); 
            Point p = new Point( hexmech.pxtoHex(e.getX(),e.getY()) );
            if (p.x < 0 || p.y < 0 || p.x >= COLUMN_SIZE || p.y >= ROW_SIZE) return;

            board[p.x][p.y] = CLICKED;
            repaint();
        }        
    }
}
}

Hexmech

package hex;

import java.awt.*;
import javax.swing.*;

public class hexmech
{

 #define HEXEAST 0
 #define HEXSOUTHEAST 1
 #define HEXSOUTHWEST 2
 #define HEXWEST 3
 #define HEXNORTHWEST 4
 #define HEXNORTHEAST 5

public final static boolean orFLAT= true;
public final static boolean orPOINT= false;
public static boolean ORIENT= orFLAT;

public static boolean XYVertex=true;

private static int BORDERS=50

private static int s=0; // length of one side
private static int t=0; // short side of 30o triangle outside of each hex
private static int r=0; // radius of inscribed circle (centre to middle of each side). r= h/2
private static int h=0; // height. Distance between centres of two adjacent hexes. Distance between two opposite sides in a hex.

public static void setXYasVertex(boolean b) {
    XYVertex=b;
}
public static void setBorders(int b){
    BORDERS=b;
}

public static void setSide(int side) {
    s=side;
    t =  (int) (s / 2);         //t = s sin(30) = (int) CalculateH(s);
    r =  (int) (s * 0.8660254037844);
    h=2*r;
}
public static void setHeight(int height) {
    h = height;
    r = h/2;            // r = radius of inscribed circle
    s = (int) (h / 1.73205);    // s = (h/2)/cos(30)= (h/2) / (sqrt(3)/2) = h / sqrt(3)
    t = (int) (r / 1.73205);    // t = (h/2) tan30 = (h/2) 1/sqrt(3) = h / (2 sqrt(3)) = r / sqrt(3)
}


public static Polygon hex (int x0, int y0) {

    int y = y0 + BORDERS;
    int x = x0 + BORDERS;

    if (s == 0  || h == 0) {
        System.out.println("ERROR: size of hex has not been set");
        return new Polygon();
    }

    int[] cx,cy;


    if (XYVertex) 
        cx = new int[] {x,x+s,x+s+t,x+s,x,x-t};  //this is for the top left vertex being at x,y. Which means that some of the hex is cutoff.
    else
        cx = new int[] {x+t,x+s+t,x+s+t+t,x+s+t,x+t,x}; //this is for the whole hexagon to be below and to the right of this point

    cy = new int[] {y,y,y+r,y+r+r,y+r+r,y+r};
    return new Polygon(cx,cy,6);

}

public static void drawHex(int i, int j, Graphics2D g2) {
    int x = i * (s+t);
    int y = j * h + (i%2) * h/2;
    Polygon poly = hex(x,y);
    g2.setColor(hexgame.COLOURCELL);
    //g2.fillPolygon(hexmech.hex(x,y));
    g2.fillPolygon(poly);
    g2.setColor(hexgame.COLOURGRID);
    g2.drawString(String.format("%c;%d", 'A'+i, j+1), x+20, y+40);
    g2.drawPolygon(poly);
}



public static void fillHex(int i, int j, int n, Graphics2D g2) {
    char c='o';
    int x = i * (s+t);
    int y = j * h + (i%2) * h/2;
    /*if (n < 0) {
        g2.setColor(hexgame.COLOURONE);
        g2.fillPolygon(hex(x,y));
        g2.setColor(hexgame.COLOURONETXT);
        c = (char)(-n);
        g2.drawString(""+c, x+r+BORDERS, y+r+BORDERS+4); //FIXME: handle XYVertex
        //g2.drawString(x+","+y, x+r+BORDERS, y+r+BORDERS+4);
    }
    if (n > 0) {
        g2.setColor(hexgame.COLOURTWO);
        g2.fillPolygon(hex(x,y));
        g2.setColor(hexgame.COLOURTWOTXT);
        c = (char)n;

    if (n==3) {
        g2.setColor(hexgame.COLOURTWO);
        g2.fillPolygon(hex(x,y));
        g2.setColor(hexgame.COLOURTWOTXT);
    }
}

public static Point pxtoHex(int mx, int my) {
    Point p = new Point(-1,-1);

    //correction for BORDERS and XYVertex
    mx -= BORDERS;
    my -= BORDERS;
    if (XYVertex) mx += t;

    int x = (int) (mx / (s+t));
    int y = (int) ((my - (x%2)*r)/h);

    int dx = mx - x*(s+t);
    int dy = my - y*h;

    if (my - (x%2)*r < 0) return p; // prevent clicking in the open halfhexes at the top of the screen

    //System.out.println("dx=" + dx + " dy=" + dy + "  > " + dx*r/t + " <");

    //even columns
    if (x%2==0) {
        if (dy > r) {   //bottom half of hexes
            if (dx * r /t < dy - r) {
                x--;
            }
        }
        if (dy < r) {   //top half of hexes
            if ((t - dx)*r/t > dy ) {
                x--;
                y--;
            }
        }
    } else {  // odd columns
        if (dy > h) {   //bottom half of hexes
            if (dx * r/t < dy - h) {
                x--;
                y++;
            }
        }
        if (dy < h) {   //top half of hexes
            //System.out.println("" + (t- dx)*r/t +  " " + (dy - r));
            if ((t - dx)*r/t > dy - r) {
                x--;
            }
        }
    }
    p.x=x;
    p.y=y;
    return p;
}
1

There are 1 answers

0
trashgod On BEST ANSWER

In your implementation of paintComponent(), invoke setClip() with a suitable Shape, such as Polygon. You can size and translate the Polygon to match the destination hexagon using the createTransformedShape() method of AffineTransform. Use the coordinates of the polygon's boundary as the basis for the coordinates used in your call to drawImage(). A related example using Ellipse2D is shown here.