在 Java 中是否有 JFrame 的有效替代方案?
Is there any efficient alternative to JFrame in Java?
我正在 Java 编写一个游戏,想将它导出到功能较弱的机器上,我已经弄清楚如何将它导出到其他平台,但是当 运行 在功能较弱的机器上它使它们升温了很多。我对我的代码做了一些检查,发现问题出在我在此 class:
中调用 JFrame 对象时
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class Display {
private JFrame frame;
private Canvas canvas;
private int screenWidth;
private int screenHeight;
public Display(int width, int height) {
this.screenHeight = height;
this.screenWidth = width;
makeDisplay();
}
public void makeDisplay() {
frame = new JFrame();
frame.setVisible(true);
frame.setSize(screenWidth, screenHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/GameIcon.png")));;
canvas = new Canvas();
canvas.setPreferredSize(new Dimension(screenWidth, screenHeight));
canvas.setMinimumSize(new Dimension(screenWidth, screenHeight));
canvas.setMaximumSize(new Dimension(screenWidth, screenHeight));
canvas.setFocusable(false);
frame.add(canvas);
frame.pack();
}
public JFrame getFrame() {
return frame;
}
public Canvas getCanvas() {
return canvas;
}
}
当我删除 class 中的 JFrame 实例时,性能显着提高。所以我的问题是,如何使这段代码更有效率,或者是否有更有效的方法在我的代码中使用与 JFrame 类似的东西。
我研究了使图形有效地出现在 Java 中的其他方法,并得出结论,JavaFX 是可行的方法。我已经在我的 Main 函数中实现了它,根据任务管理器,代码现在使用了 <3% 的 CPU(我有一个 Intel Core i7 第 8 代)。这下降了大约 13 个百分点,所以我认为这是使我的代码更高效的重要一步。快速说明一下,KeyManager class 只保留是否按下箭头键的布尔值,而 World class 包含所有游戏逻辑。这是实现 JavaFX:
的代码
import java.io.IOException;
import battlegame.graphics.Assets;
import battlegame.input.KeyboardController;
import battlegame.world.World;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Game extends Application{
public static int screenWidth = 1248;
public static int screenHeight = 624;
private Canvas canvas;
private Stage stage;
private Scene scene;
private Group group;
private GraphicsContext g;
private final LongProperty lastUpdateTime = new SimpleLongProperty(0);
private static World currentWorld;
private static KeyboardController keyController;
public Game() {
keyController = new KeyboardController();
}
public void begin(String args[]) {
launch(args);
}
public void initialise() throws IOException {
canvas = new Canvas(screenWidth, screenHeight);
group = new Group(canvas);
scene = new Scene(group);
g = canvas.getGraphicsContext2D();
Assets.init();
currentWorld = new World("/testlvl.txt");
currentWorld.init();
}
@Override
public void start(Stage primaryStage)throws Exception {
initialise();
final AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long timestamp) {
if (lastUpdateTime.get() > 16.6666666667) {
tick();
render();
}
lastUpdateTime.set(timestamp);
}
};
stage = primaryStage;
stage.getIcons().add(new Image(Game.class.getResourceAsStream("/GameIcon.png")));
stage.setScene(scene);
stage.setResizable(false);
stage.setOnCloseRequest(event -> {
timer.stop();
});
stage.show();
scene.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = true;
}
if(key.getCode() == KeyCode.A || key.getCode() == KeyCode.LEFT) {
keyController.left = true;
}
if(key.getCode() == KeyCode.S || key.getCode() == KeyCode.DOWN) {
keyController.down = true;
}
if(key.getCode() == KeyCode.D || key.getCode() == KeyCode.RIGHT) {
keyController.right = true;
}
if(key.getCode() == KeyCode.Z || key.getCode() == KeyCode.O || key.getCode() == KeyCode.ENTER) {
keyController.select = true;
}
if(key.getCode() == KeyCode.P || key.getCode() == KeyCode.X) {
keyController.action = true;
}
});
scene.addEventHandler(KeyEvent.KEY_TYPED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = true;
}
});
scene.addEventHandler(KeyEvent.KEY_RELEASED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = false;
}
if(key.getCode() == KeyCode.A || key.getCode() == KeyCode.LEFT) {
keyController.left = false;
}
if(key.getCode() == KeyCode.S || key.getCode() == KeyCode.DOWN) {
keyController.down = false;
}
if(key.getCode() == KeyCode.D || key.getCode() == KeyCode.RIGHT) {
keyController.right = false;
}
if(key.getCode() == KeyCode.Z || key.getCode() == KeyCode.O || key.getCode() == KeyCode.ENTER) {
keyController.select = false;
}
if(key.getCode() == KeyCode.P || key.getCode() == KeyCode.X) {
keyController.action = false;
} });
timer.start();
}
public void tick() {
keyController.tick();
currentWorld.tick();
}
public void render() {
g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
currentWorld.render(g);
}
public static void main(String[] args){
launch();
}
public static KeyboardController getKeyController(){
return keyController;
}
public static World getCurrentWorld() {
return currentWorld;
}
}
我正在 Java 编写一个游戏,想将它导出到功能较弱的机器上,我已经弄清楚如何将它导出到其他平台,但是当 运行 在功能较弱的机器上它使它们升温了很多。我对我的代码做了一些检查,发现问题出在我在此 class:
中调用 JFrame 对象时import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class Display {
private JFrame frame;
private Canvas canvas;
private int screenWidth;
private int screenHeight;
public Display(int width, int height) {
this.screenHeight = height;
this.screenWidth = width;
makeDisplay();
}
public void makeDisplay() {
frame = new JFrame();
frame.setVisible(true);
frame.setSize(screenWidth, screenHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/GameIcon.png")));;
canvas = new Canvas();
canvas.setPreferredSize(new Dimension(screenWidth, screenHeight));
canvas.setMinimumSize(new Dimension(screenWidth, screenHeight));
canvas.setMaximumSize(new Dimension(screenWidth, screenHeight));
canvas.setFocusable(false);
frame.add(canvas);
frame.pack();
}
public JFrame getFrame() {
return frame;
}
public Canvas getCanvas() {
return canvas;
}
}
当我删除 class 中的 JFrame 实例时,性能显着提高。所以我的问题是,如何使这段代码更有效率,或者是否有更有效的方法在我的代码中使用与 JFrame 类似的东西。
我研究了使图形有效地出现在 Java 中的其他方法,并得出结论,JavaFX 是可行的方法。我已经在我的 Main 函数中实现了它,根据任务管理器,代码现在使用了 <3% 的 CPU(我有一个 Intel Core i7 第 8 代)。这下降了大约 13 个百分点,所以我认为这是使我的代码更高效的重要一步。快速说明一下,KeyManager class 只保留是否按下箭头键的布尔值,而 World class 包含所有游戏逻辑。这是实现 JavaFX:
的代码import java.io.IOException;
import battlegame.graphics.Assets;
import battlegame.input.KeyboardController;
import battlegame.world.World;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Game extends Application{
public static int screenWidth = 1248;
public static int screenHeight = 624;
private Canvas canvas;
private Stage stage;
private Scene scene;
private Group group;
private GraphicsContext g;
private final LongProperty lastUpdateTime = new SimpleLongProperty(0);
private static World currentWorld;
private static KeyboardController keyController;
public Game() {
keyController = new KeyboardController();
}
public void begin(String args[]) {
launch(args);
}
public void initialise() throws IOException {
canvas = new Canvas(screenWidth, screenHeight);
group = new Group(canvas);
scene = new Scene(group);
g = canvas.getGraphicsContext2D();
Assets.init();
currentWorld = new World("/testlvl.txt");
currentWorld.init();
}
@Override
public void start(Stage primaryStage)throws Exception {
initialise();
final AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long timestamp) {
if (lastUpdateTime.get() > 16.6666666667) {
tick();
render();
}
lastUpdateTime.set(timestamp);
}
};
stage = primaryStage;
stage.getIcons().add(new Image(Game.class.getResourceAsStream("/GameIcon.png")));
stage.setScene(scene);
stage.setResizable(false);
stage.setOnCloseRequest(event -> {
timer.stop();
});
stage.show();
scene.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = true;
}
if(key.getCode() == KeyCode.A || key.getCode() == KeyCode.LEFT) {
keyController.left = true;
}
if(key.getCode() == KeyCode.S || key.getCode() == KeyCode.DOWN) {
keyController.down = true;
}
if(key.getCode() == KeyCode.D || key.getCode() == KeyCode.RIGHT) {
keyController.right = true;
}
if(key.getCode() == KeyCode.Z || key.getCode() == KeyCode.O || key.getCode() == KeyCode.ENTER) {
keyController.select = true;
}
if(key.getCode() == KeyCode.P || key.getCode() == KeyCode.X) {
keyController.action = true;
}
});
scene.addEventHandler(KeyEvent.KEY_TYPED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = true;
}
});
scene.addEventHandler(KeyEvent.KEY_RELEASED, (key) -> {
if(key.getCode() == KeyCode.W || key.getCode() == KeyCode.UP || key.getCode() == KeyCode.SPACE) {
keyController.up = false;
}
if(key.getCode() == KeyCode.A || key.getCode() == KeyCode.LEFT) {
keyController.left = false;
}
if(key.getCode() == KeyCode.S || key.getCode() == KeyCode.DOWN) {
keyController.down = false;
}
if(key.getCode() == KeyCode.D || key.getCode() == KeyCode.RIGHT) {
keyController.right = false;
}
if(key.getCode() == KeyCode.Z || key.getCode() == KeyCode.O || key.getCode() == KeyCode.ENTER) {
keyController.select = false;
}
if(key.getCode() == KeyCode.P || key.getCode() == KeyCode.X) {
keyController.action = false;
} });
timer.start();
}
public void tick() {
keyController.tick();
currentWorld.tick();
}
public void render() {
g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
currentWorld.render(g);
}
public static void main(String[] args){
launch();
}
public static KeyboardController getKeyController(){
return keyController;
}
public static World getCurrentWorld() {
return currentWorld;
}
}