【问题标题】:Create hexagonal field with JavaFX使用 JavaFX 创建六边形字段
【发布时间】:2019-06-07 12:02:58
【问题描述】:

我的目标是创建一个六边形瓷砖场。我已经有了一个单元矩阵,每个单元都足够高以适应完整的六边形图像:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class UITest extends Application {
    final private static String TILE_IMAGE_LOCATION = System.getProperty("user.dir") + File.separatorChar +"resources"+ File.separatorChar + "blueTile.png";
    final private static Image HEXAGON_IMAGE = initTileImage();

    private static Image initTileImage() {
        try {
            return new Image(new FileInputStream(new File(TILE_IMAGE_LOCATION)));
        } catch (FileNotFoundException e) {
            throw new IllegalStateException(e);
        }
    }
    public void start(Stage primaryStage) {
        int height = 4;
        int width = 6;
        GridPane tileMap = new GridPane();
        Scene content = new Scene(tileMap, 800, 600);
        primaryStage.setScene(content);

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                ImageView tile = new ImageView(HEXAGON_IMAGE);
                GridPane.setConstraints(tile, x, y);
                tileMap.getChildren().add(tile);
            }
        }

        primaryStage.show();
    }
}

我的问题不在于垂直间隙,我可以通过将 GridPane 的 vGap() 添加到适当的值来确定。对我来说,困难是每第二行向右移动半个单元格宽度。

我尝试将两个 GridPanes 放在彼此之上,一个包含奇数行,一个包含偶数行,目的是为其中一个添加填充,完全移动它。然而,据我所知,除了将 GridPanes 嵌套到另一个上之外,没有办法做到这一点。

我怎样才能最好地实现每隔一行移动一次?

(我在代码中引用的图像应该在${projectroot}/resources/ 文件夹中:

【问题讨论】:

    标签: javafx hexagonal-tiles


    【解决方案1】:

    对于其他感兴趣的人,我使用了 Cthulhu 接受的答案,并改进/记录了给定的代码作为一个简短的独立演示:

    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));
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我花了一些时间才弄明白。我希望它有所帮助。我不使用图像。它由多边形组成,您可以自定义描边和填充颜色以及宽度。

      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.stage.Stage;
      import javafx.scene.layout.AnchorPane;
      import javafx.scene.paint.Paint;
      import javafx.scene.shape.Polygon;
      
      public class UITest extends Application {
          public void start(Stage primaryStage) {
              int height = 600;
              int width = 800;
              AnchorPane tileMap = new AnchorPane();
              Scene content = new Scene(tileMap, width, height);
              primaryStage.setScene(content);
              double size = 50,v=Math.sqrt(3)/2.0;
              for(double y=0;y<height;y+=size*Math.sqrt(3))
              {
                  for(double x=-25,dy=y;x<width;x+=(3.0/2.0)*size)
                  {
                      Polygon tile = new Polygon();
                      tile.getPoints().addAll(new Double[]{
                          x,dy,
                          x+size,dy,
                          x+size*(3.0/2.0),dy+size*v,
                          x+size,dy+size*Math.sqrt(3),
                          x,dy+size*Math.sqrt(3),
                          x-(size/2.0),dy+size*v
                      });
                      tile.setFill(Paint.valueOf("#ffffff"));
                      tile.setStrokeWidth(2);
                      tile.setStroke(Paint.valueOf("#000000") );
                      tileMap.getChildren().add(tile);
                      dy = dy==y ? dy+size*v : y;
                  }
              }
              primaryStage.show();
          }
          public static void main(String[] args)
          {
              launch(args);
          }
      }
      

      【讨论】:

      • 这实际上也解决了另一个问题。非常感谢!
      猜你喜欢
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 2014-02-11
      相关资源
      最近更新 更多