I want to create an hexagonal field with flat tiles in JavaFX. The following stackoverflow question allows to create a field with pointy tiles: Create hexagonal field with JavaFX
This code example works perfectly with pointy tiles:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;
public class UISolution extends Application {
private final static int WINDOW_WIDTH = 800;
private final static int WINDOW_HEIGHT = 600;
private final static double r= 20; // the inner radius from hexagon center to outer corner
private final static double n= Math.sqrt(r * r * 0.75); // the inner radius from hexagon center to middle of the axis
private final static double TILE_HEIGHT = 2 * r;
private final static double TILE_WIDTH = 2 * n;
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
AnchorPane tileMap = new AnchorPane();
Scene content = new Scene(tileMap, WINDOW_WIDTH, WINDOW_HEIGHT);
primaryStage.setScene(content);
int rowCount = 4; // how many rows of tiles should be created
int tilesPerRow = 6; // the amount of tiles that are contained in each row
int xStartOffset = 40; // offsets the entire field to the right
int yStartOffset = 40; // offsets the entire fiels downwards
for (int x = 0; x < tilesPerRow; x++) {
for (int y = 0; y < rowCount; y++) {
double xCoord = x * TILE_WIDTH + (y % 2) * n + xStartOffset;
double yCoord = y * TILE_HEIGHT * 0.75 + yStartOffset;
Polygon tile = new Tile(xCoord, yCoord);
tileMap.getChildren().add(tile);
}
}
primaryStage.show();
}
private class Tile extends Polygon {
Tile(double x, double y) {
// creates the polygon using the corner coordinates
getPoints().addAll(
x, y,
x, y + r,
x + n, y + r * 1.5,
x + TILE_WIDTH, y + r,
x + TILE_WIDTH, y,
x + n, y - r * 0.5
);
// set up the visuals and a click listener for the tile
setFill(Color.ANTIQUEWHITE);
setStrokeWidth(1);
setStroke(Color.BLACK);
setOnMouseClicked(e -> System.out.println("Clicked: " + this));
}
}
}
I think that I only have to modify the part here:
getPoints().addAll(
x, y,
x, y + r,
x + n, y + r * 1.5,
x + TILE_WIDTH, y + r,
x + TILE_WIDTH, y,
x + n, y - r * 0.5
);
but I'm struggling to have a correct shape and position for my tiles. And if I'm doing:
getPoints().addAll(x, y,
x + n * 0.5, y + r,
x + n * 1.5, y + r,
x + TILE_WIDTH, y,
x + n * 1.5, y - r,
x + n * 0.5, y - r
);
the tiles have a correct flat shape but are not positioned correctly relative to each other. I think that this time I should modify the following code:
double xCoord = x * TILE_WIDTH + (y % 2) * n + xStartOffset;
double yCoord = y * TILE_HEIGHT * 0.75 + yStartOffset;
An example of the pointy tiles result with this code:
I found a solution for flat tiles. Here it is:
package org.hexagon.check;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
public class HexagonFlat extends Application {
private final static double TILE_WIDTH = 20;
private final static double TILE_HEIGHT = TILE_WIDTH;
private final static int WINDOW_WIDTH = 800;
private final static int WINDOW_HEIGHT = 600;
double v = Math.sqrt(3) / 2.0;
double v2 = Math.sqrt(3);
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
AnchorPane tileMap = new AnchorPane();
Scene content = new Scene(tileMap, WINDOW_WIDTH, WINDOW_HEIGHT);
primaryStage.setScene(content);
int rowCount = 4; // how many rows of tiles should be created
int tilesPerRow = 6; // the amount of tiles that are contained in each row
int xStartOffset = 40; // offsets the entire field to the right
int yStartOffset = 40; // offsets the entire fiels downwards
for (int y = 0; y < rowCount; y++) {
double yCoordInit = yStartOffset + y * TILE_WIDTH * v2;
double yCoord = yCoordInit;
for (int x = 0; x < tilesPerRow; x++) {
double xCoord = 1.5 * x * TILE_WIDTH + xStartOffset;
Polygon tile = new Tile(xCoord, yCoord);
tileMap.getChildren().add(tile);
yCoord = yCoord == yCoordInit ? yCoord + TILE_HEIGHT * v : yCoordInit;
}
}
primaryStage.show();
}
private class Tile extends Polygon {
Tile(double x, double y) {
// creates the polygon using the corner coordinates
getPoints().addAll(
x, y,
x + TILE_WIDTH, y,
x + TILE_WIDTH * 1.5, y + TILE_HEIGHT * v,
x + TILE_WIDTH, y + TILE_HEIGHT * v2,
x, y + TILE_WIDTH * v2,
x - (TILE_WIDTH / 2.0), y + TILE_HEIGHT * v
);
// set up the visuals and a click listener for the tile
setFill(Color.ANTIQUEWHITE);
setStrokeWidth(1);
setStroke(Color.BLACK);
setOnMouseClicked(e -> System.out.println("Clicked: " + this));
}
}
}
The result is: