【问题标题】:JavaFX performance issues with ImagePattern on canvas画布上 ImagePattern 的 JavaFX 性能问题
【发布时间】:2021-06-24 07:59:06
【问题描述】:

我正在开发一个在 JavaFX 中使用六边形网格作为地图的 2D 游戏。

我使用Canvas 通过fillPolygon() 绘制自定义Hexagon 对象,现在想用项目中包含的ImagePattern 对象填充这些六边形,作为.png 文件大小为100x100 像素。

在尝试使用 AnimationTimer 将游戏置于渲染循环中时,我遇到了一些性能问题。

使用ImagePattern 绘制地图只能给我10-20 FPS,而使用Color 作为填充给我相当稳定的60 FPS。 ImagePattern 是从应用程序启动时构造的 HashMap<TerrainType, ImagePattern> 加载的。

绘制方法的主要部分如下所示:

boardGraphicsContext.setFill(
    resourceMap.getTerrainSprite(gameBoardNodes[i][j].getTerrainType())
);

boardGraphicsContext.fillPolygon(
    Hexagon.polygonCornersX(layout, hex), 
    Hexagon.polygonCornersY(layout, hex), 
    6
);

我也尝试在进入循环之前设置填充,根本不改变它,这也没有提高性能。

地图由 20x20 六边形组成。

以防万一:我使用的是 2017 年的 MacBook Pro,配备一些双核 i5 和 Intel Iris Plus Graphics 640,内存为 1536MB。

是否有可能使用画布方法提高性能?

问候

更新:

这里的实际问题是,现在使用 .png 作为使用 MacBook 触控板滚动的六边形的纹理似乎相当缓慢,而使用纯色则更平滑。我不知道这是我的计算机、JavaFX 还是我的特定实现的限制。

在我最初的帖子中,我说过我正在使用 Canvas 来绘制游戏,但下面的场景图实现与 Canvas 实现存在相同的问题,但更紧凑,更适合发布。

package sample;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

import java.util.HashMap;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        AnchorPane boardPane = new AnchorPane();
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 20; j++) {
                HexNode newNode = new HexNode(i, j, "GRASS");
                boardPane.getChildren().add(newNode);
            }
        }

        boardPane.setOnScroll(scrollEvent -> {
            double deltaY = scrollEvent.getDeltaY();
            double zoomFactor = 1.05;

            if (deltaY < 0){
                zoomFactor = 2.0 - zoomFactor;
            }

            boardPane.setScaleX(boardPane.getScaleX() * zoomFactor);
            boardPane.setScaleY(boardPane.getScaleY() * zoomFactor);
        });

        primaryStage.setScene(new Scene(boardPane));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class HexNode extends Polygon {
    private final String type;
    private final ResourceMap resourceMap = ResourceMap.getInstance();

    public HexNode(int x, int y, String type) {
        super();
        double height = 50;
        this.type = type;

        double r = height / 2.0;
        double h = r * Math.sin(Math.toRadians(30));
        double w = r * Math.cos(Math.toRadians(30));

        double xOffset, yOffset;
        if (y % 2 == 0) {
            xOffset = 2 * w * x;
        } else {
            xOffset = 2 * w * x + w;
        }
        yOffset = 2 * r * y - (y * h);

        this.getPoints().addAll(
                w + xOffset, 0.0 + yOffset,
                2 * w + xOffset, h + yOffset,
                2 * w + xOffset, 2 * r - h + yOffset,
                w + xOffset, 2 * r + yOffset,
                0.0 + xOffset, 2 * r - h + yOffset,
                0.0 + xOffset, h + yOffset
        );

        drawType();
    }

    private void drawType() {
        this.setFill(new ImagePattern(resourceMap.getTerrainSprite(type)));
        // this.setFill(Color.BLACK); is much better
    }
}

class ResourceMap {

    private static final ResourceMap instance = new ResourceMap();
    private final HashMap<String, Image> terrainSprites = new HashMap<>();

    private ResourceMap() {
        terrainSprites.put("GRASS", loadSpriteFromPath("PATH_TO_PNG"));
    }

    public static ResourceMap getInstance() {
        return instance;
    }

    public Image getTerrainSprite(String terrainType) {
        return terrainSprites.get(terrainType);
    }

    private Image loadSpriteFromPath(String filePath) {
        return new Image(filePath);
    }
}

【问题讨论】:

标签: java javafx


【解决方案1】:

在我看来,您为此目的使用了完全错误的方法。你应该使用场景图而不是画布。然后,您可以将一些 ImageViews 放在一个网格中,然后随意移动该区域,而不会影响性能。我经常做这样的事情。看看这里,例如:https://twitter.com/MichaelPaus/status/1272197273313738752/photo/1

【讨论】:

  • 我使用场景图和多边形对象实现了一个版本,并得到了非常相似的结果。如果我使用简单的颜色作为多边形的填充,缩放时的性能非常好。如果我使用 ImagePattern,性能会下降到 Canvas/ImagePattern 实现的水平。
  • 这很奇怪,但这里出了什么问题只能通过更深入地了解您的实际代码来回答。
  • 我用更多代码更新了我的初始帖子。
  • 但是您显示的新代码可能与您的问题无关。您遇到了性能问题,但您只显示了明显有效的一次性初始化代码,否则您不仅会抱怨性能。真正的问题是如何在每个动画步骤中使用该代码?
  • 游戏中没有实际的动画,它是一个静态棋盘游戏,要求是缩放和平移游戏板,而缩放部分是我遇到的问题。我添加了一个问题的最小示例,而不是我的初始化代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
相关资源
最近更新 更多