首页 > 解决方案 > 在 JavaFX 中,如何在画布上绘制一个移动的字符在窗口的中心?

问题描述

我对 JavaFX 非常陌生,目前正在开发一款类似 2D 的胭脂游戏,它使用 JavaFX 制作的 GUI。使用 GraphicContext2D 在画布上绘制移动角色。只有一个画布,如果可能的话,我想在不覆盖的情况下解决我的问题。画布作为中心添加到 Borderpane,使用此 Borderpane 创建的场景,用于设置此 Scene 的 Stage。在 KeyEvent 上随角色移动后重新绘制画布。我已经使舞台可调整大小。一切都运行良好,除了我不能将我的移动角色保持在窗口的中心并且当画布大于窗口时它可以移出这个窗口。我怎样才能让我亲爱的移动角色保持在中间?

好的,这是一个非常非常简化的版本,但同样的问题是,字符不会停留在中间,它可以从窗口中跑出然后返回,因为画布设置为大于窗口。

public class Main extends Application {

    String[][] map = new String[40][20];
    int[] playerCoords = {3,10};

    //colored.png downloaded from https://kenney.nl/assets/bit-pack
    Image tileset = new Image("/colored.png", 815 * 2, 373 * 2, true, false);
    Canvas canvas = new Canvas(
            20 * 32,
            40 * 32);
    GraphicsContext context = canvas.getGraphicsContext2D();

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

    @Override
    public void start(Stage stage){
        BorderPane borderPane = new BorderPane();
        borderPane.setCenter(canvas);
        map[3][10] = "p";

        refresh();
        Scene scene = new Scene(borderPane);
        scene.setOnKeyPressed(keyEvent -> {switch (keyEvent.getCode()) {
            case UP:
                this.movePlayer(true);
                refresh();
                break;
            case DOWN:
                this.movePlayer(false);
                refresh();
                break;}});
        stage.setScene(scene);
        stage.show();
    }

    void movePlayer(boolean up){
        int direction = up ? -1 : 1;
        int newPosRow = playerCoords[0] + direction;
        if ( newPosRow >= 0 && newPosRow < map.length) {
            map[playerCoords[0]][playerCoords[1]] = null;
            playerCoords[0] = newPosRow;
            map[playerCoords[0]][playerCoords[1]] = "p";
        }
    }

    void refresh(){
        context.setFill(Color.BLACK);
        context.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
        for (int i = 0; i < map.length; i++ ){
            for (int j = 0; j < map[0].length; j++){
                if (map[i][j] != null && map[i][j].equals("p")){
                    //player Tile 28, 0
                    context.drawImage(tileset, 952,0, 32,32,j * 32,i * 32, 32,32);
                } else{
                    context.drawImage(tileset, 0,0, 32,32,j * 32,i * 32, 32,32);
                }
            }
        }
    }

}

标签: javafxcanvas

解决方案


好的,所以目前似乎没有一个简单的 JavaFX 解决方案。但是如果有人知道,谢谢分享。:-) 与此同时,我考虑了一个算法解决方案,通过根据玩家的绝对和相对(放置在中间的玩家)坐标转换坐标。它远非完美,它仅更改地图的 rowCoords,因为在此示例中玩家只能垂直移动,并且它适用于不大于窗口大小的画布。我只需要更改刷新方法。目前有一些我不明白的东西,它适用于从玩家的行坐标中减去 centerCol

int centerRow = map.length/2;
int centerCol = map[0].length/2;
int mapRowDiff = playerCoords[0] - centerCol;

不是从玩家的行坐标中减去 centerRow

int centerRow = map.length/2;
int centerCol = map[0].length/2;
int mapRowDiff = playerCoords[0] -  centerRow; 

但至少它开始起作用了。这是我的 refresh() 与转换,它变得有点复杂。

    void refresh(){
        context.setFill(Color.BLACK);
        context.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
        int centerRow = map.length/2;
        int centerCol = map[0].length/2;
        int mapRowDiff = playerCoords[0] - centerCol;
        for (int i = 0; i < map.length; i++ ){
            for (int j = 0; j < map[0].length; j++){
                if (mapRowDiff >= 0
                        && mapRowDiff < map.length) {
                    if (map[mapRowDiff][j] != null && map[mapRowDiff][j].equals("p")) {
                        //player Tile 28, 0
                        context.drawImage(tileset, 952, 0, 32, 32, j * 32, i * 32, 32, 32);
                    } else {
                        context.drawImage(tileset, 0, 0, 32, 32, j * 32, i * 32, 32, 32);
                    }
                } else {
                    context.drawImage(tileset, 0, 34, 32, 32, j * 32, i * 32, 32, 32);
                }
            }
            mapRowDiff++;
        }
    }

推荐阅读