JavaFX 通过 setOnKeyPressed 更新当前位置

标签 java javafx

我目前正在学习 JavaFX,我决定制作一个简单的冒险游戏。具有可用导出的位置的描述显示在文本区域中,并且用户在文本字段中键入他想要前往的方向。但是,我遇到了一个问题:选择方向后,我必须再次按 Enter 才能正确更新当前位置和可用导出。我发现,在当前版本中,这是由于我更新负责当前位置描述的“loc”变量的方式所致。我不知道如何解决它,或者我应该如何改变它的工作方式。有人可以帮我吗?预先感谢您的帮助

位置类别:

package sample.LocationsSystem;

import java.util.HashMap;
import java.util.Map;

public class Location {
private final int locationID;
private final String description;
private final Map<String, Integer> exits;

public Location(int locationID, String description) {
    this.locationID = locationID;
    this.description = description;
    this.exits = new HashMap<>();
}

public void addExit(String direction, int location) {
    exits.put(direction, location);
}

public int getLocationID() {
    return locationID;
}

public String getDescription() {
    return description;
}

public Map<String, Integer> getExits() {
    return new HashMap<String, Integer>(exits);
}
}

带有描述和导出的位置:

package sample.LocationsSystem;

import java.util.HashMap;
import java.util.Map;

public class Locations {

private static Map<Integer, Location> locationsMap = new HashMap<>();

public Locations() {
    initializeMap();
}

public static Map<Integer, Location> getLocationsMap() {
    return locationsMap;
}

public static void initializeMap(){
    locationsMap.put(0, new Location(0,"You entered the dungeon"));
    locationsMap.put(1, new Location(1,"You are in a narrow corridor"));
    locationsMap.put(2, new Location(2,"You are in round basement. You can see many doors around you"));
    locationsMap.put(3, new Location(3,"You are in a dark corridor. Strange noises are coming from the door just before you"));
    locationsMap.put(4, new Location(4,"Location 4"));
    locationsMap.put(5, new Location(5,"It's nothing here. Turn back"));
    locationsMap.put(6, new Location(6,"It's a broom cupboard."));
    locationsMap.put(7, new Location(7,"It's just a corridor"));
    locationsMap.put(8, new Location(8,"You entered into old throne room"));
    locationsMap.put(9, new Location(9,"It looks like an old armory"));
    locationsMap.put(10, new Location(10,"You can see a large pile of gold coins. That's what you came here for."));


    locationsMap.get(0).addExit("W",1);

    locationsMap.get(1).addExit("N",2);
    locationsMap.get(1).addExit("E",0);

    locationsMap.get(2).addExit("N",6);
    locationsMap.get(2).addExit("S",1);
    locationsMap.get(2).addExit("E",3);
    locationsMap.get(2).addExit("W",5);

    locationsMap.get(5).addExit("E",2);

    locationsMap.get(6).addExit("S",2);

    locationsMap.get(3).addExit("E",4);
    locationsMap.get(3).addExit("W",2);

    locationsMap.get(4).addExit("N",7);
    locationsMap.get(4).addExit("W",3);

    locationsMap.get(7).addExit("S",4);
    locationsMap.get(7).addExit("E",8);

    locationsMap.get(8).addExit("N",10);
    locationsMap.get(8).addExit("S",9);
    locationsMap.get(8).addExit("W",7);

    locationsMap.get(9).addExit("N",8);


    Map<String, String> vocabulary = new HashMap<String, String>();
    vocabulary.put("NORTH", "N");
    vocabulary.put("SOUTH", "S");
    vocabulary.put("WEST", "W");
    vocabulary.put("EAST", "E");
}
}

还有我的 Controller 类:

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import sample.Characters.Player;
import sample.FightSystem.Fight;
import sample.LocationsSystem.Locations;

import java.util.Map;


public class Controller {

@FXML
TextField HPTextField;

@FXML
TextField enemyHP;

@FXML
TextField potionsTextField;

@FXML
TextField textField;

@FXML
TextArea mainTextArea;

public void clearTextField() {
    textField.clear();
}

int loc = 0;
public void initialize() {

    Player player = new Player("Player", 100, 10);
    Fight fight = new Fight();

    HPTextField.setText(Integer.toString(player.getHp()));
    potionsTextField.setText(Integer.toString(player.getPotions().size()));

    mainTextArea.setText("Welcome to adventure game! \n=======PRESS ENTER TO START======");

    Locations locations = new Locations();
    Map<String, Integer> exits = locations.getLocationsMap().get(loc).getExits();

    textField.setOnKeyPressed(keyEvent -> {
        if (keyEvent.getCode().equals(KeyCode.ENTER)) {

            String direction = textField.getText().toUpperCase();

            mainTextArea.appendText(locations.getLocationsMap().get(loc).getDescription()
                    + "\n In which direction would you like to go? \nAvailable directions: ");

            for (String exit : exits.keySet()) {
                mainTextArea.appendText(exit + " ");
            }

            if (exits.containsKey(direction)) {
                loc = exits.get(direction);
            }
            textField.clear();
        }
    });
}
}

最佳答案

这里是一个示例,旨在让您了解如何继续执行此操作并解决您当前遇到的位置设置问题。

示例的作用是移动到起始位置,然后,每次用户移动到新位置时,更新位置,并在提供的文本区域中向用户提供适当的反馈。

与您问题中的主要区别在于,以下代码将立即更新当前位置引用,并在移动到新位置后立即提供有关移动的反馈,而不是在下次按键时提供反馈按下。

private static final int STARTING_LOC = 0;
private Locations locations = new Locations();
private int loc;

private TextArea mainTextArea = new TextArea();
private TextField textField = new TextField();

public void initialize() {
    mainTextArea.setText("Welcome to adventure game!");
    moveTo(STARTING_LOC);

    textField.setOnKeyPressed(keyEvent -> {
        if (keyEvent.getCode().equals(KeyCode.ENTER)) {
            String direction = textField.getText().toUpperCase();
            Integer newLoc = getCurrentExits().get(direction);
            if (newLoc != null) {
                moveTo(newLoc);
            }

            textField.setText("");
        }
    });
}

private void moveTo(int newLoc) {
    this.loc = newLoc;
    mainTextArea.appendText(
        locations.getLocationsMap().get(loc).getDescription()
            + "\n In which direction would you like to go? \nAvailable directions: "
    );
    for (String exit : getCurrentExits().keySet()) {
        mainTextArea.appendText(exit + " ");
    }
}

private Map<String, Integer> getCurrentExits() {
    return locations.getLocationsMap().get(loc).getExits();
}

该示例大致基于您问题中的代码,因此编译它所需的一些代码包含在您的问题中,而不是此答案中。该示例并非旨在演示创建冒险游戏的最佳实践。它只是一个简短的片段,而不是一个完整的程序,并且不与 FXML 绑定(bind)。它还假设您的 Locations 类的静态方法被替换为非静态方法。

不相关的建议

您可能会考虑采取不同的做法:

  1. 使用enumerated types根据需要,例如 Direction枚举类型而不是 HashMap。
  2. 将您的位置数据存储在 JSON 文件中,使用 Jackson 读取。也可以考虑使用关系数据库,但事实证明 JSON 可能更容易使用,除非您最终遇到了更复杂的需求。
  3. 使用人类可读的名称命名位置,并使用相同的名称(而不是整数)来引用导出。
  4. 使用对位置对象的引用,而不是索引 int ID 值。例如, getCurrentExits 可能返回 Map<Direction, Location>而不是Map<String, Integer> ,这样您的数据结构中就有了更具代表性的类型化信息。
  5. 从 UI 中抽象出核心游戏引擎,使其能够独立于 UI 进行开发和测试,然后根据需要将游戏引擎模型实例和服务实例调用注入(inject)到 UI 界面中。

您目前所拥有的一开始就很好,您不需要实现任何建议的想法(它们可能会使您的应用程序变得更加复杂而不是不那么复杂,您在这个阶段可能会避免这种情况),它们如果您想将应用程序开发成更大或更复杂的东西,这只是我在查看您的代码时想到的一些事情。

关于JavaFX 通过 setOnKeyPressed 更新当前位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59615585/

相关文章:

java - ListPreference 默认值未在首选项中设置

java - 在 Android 中打开文件

hashmap - JavaFX:使用 HashMap 绑定(bind)向 TableView 添加行

java - 规则 "-fx-text-alignment"不起作用?

java - 为恒定时间 contains() 创建一个 HashMap 和一个 ArrayList 是一个有效的策略吗?

java - 适用于 Ubuntu 12.10 的 Android 模拟器(Arm 安装)?

java - 使用 JUnit 测试控制台输出

JavaFX 自定义 TextField 限制

JavaFX MediaPlayer 不播放 JAR 文件中的 MP4 视频

JavaFX FileChooser 新文件