在 JavaFX 中访问 GraphicsContext 中的元素 canvas
Accessing elements inside a GraphicsContext in JavaFX canvas
我正在按照 MVC 模式实现一个简单的曲棍球游戏。我无法刷新玩家的位置,这是我使用 GraphicsContext.drawImage()
方法在 canvas 中创建的。我在 AnimationTimer
匿名 class 中,在 handle
方法中。
位置和边界都反映到后端,所以我真的不需要在这里做任何特定的逻辑,我只是想根据模型内部计算的位置在每一帧刷新玩家的位置,但我无法以任何方式访问我之前绘制的图像。这是代码:
DefaultController controller;
@FXML
public void initialize() {
controller = new DefaultController(800, 400);
double playerX = controller.getField().getPlayer().getX();
double playerY = controller.getField().getPlayer().getY();
double enemyX = controller.getField().getEnemy().getX();
double enemyY = controller.getField().getEnemy().getY();
context.drawImage(new Image("player.png"),playerX, playerY);
context.drawImage(new Image("enemy.png"),enemyX, enemyY);
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
pane.getScene().addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if (key.getCode() == KeyCode.UP) {
controller.getField().getPlayer().setLocation(playerX,playerY-0.1)
// how do I update the player image position inside the canvas?
}
});
}
};
timer.start();
}
您采用了完全错误的方法。 Canvas 中的任何内容一旦绘制完成就无法更新。您可以将其擦除并重新绘制。对于您正在尝试做的事情,场景图更适合。
以下是 mre 演示如何使用向上键在 canvas 上移动图像:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
private static final int SIZE = 200;
private static final String FISH_IMAGE = "https://www.shareicon.net/data/128x128/2015/03/28/14104_animal_256x256.png";
private Image image;
private Canvas canvas;
private final double xPos = 250;
private double yPos = 150;
private static final double MOVE = 0.8;
@Override
public void start(Stage primaryStage) {
image = new Image(FISH_IMAGE,SIZE,SIZE,false,false);
canvas = new Canvas(SIZE*3, SIZE*3);
draw();
Scene scene = new Scene(new StackPane(canvas));
scene.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> animate(key));
primaryStage.setScene(scene);
primaryStage.show();
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
//to avoid multiple handlers do not add handler here
draw();
}
};
timer.start();
}
private void animate(KeyEvent key){
if(key.getCode()== KeyCode.UP) {
yPos -= MOVE;
}
//todo add down, left , right
//for low rate animation, like response to key-press, invoke draw() here instead of using AnimationTimer
}
private void draw(){
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());//clear previous
gc.drawImage(image, xPos, yPos);
}
public static void main(String[] args) {
launch(args);
}
}
我正在按照 MVC 模式实现一个简单的曲棍球游戏。我无法刷新玩家的位置,这是我使用 GraphicsContext.drawImage()
方法在 canvas 中创建的。我在 AnimationTimer
匿名 class 中,在 handle
方法中。
位置和边界都反映到后端,所以我真的不需要在这里做任何特定的逻辑,我只是想根据模型内部计算的位置在每一帧刷新玩家的位置,但我无法以任何方式访问我之前绘制的图像。这是代码:
DefaultController controller;
@FXML
public void initialize() {
controller = new DefaultController(800, 400);
double playerX = controller.getField().getPlayer().getX();
double playerY = controller.getField().getPlayer().getY();
double enemyX = controller.getField().getEnemy().getX();
double enemyY = controller.getField().getEnemy().getY();
context.drawImage(new Image("player.png"),playerX, playerY);
context.drawImage(new Image("enemy.png"),enemyX, enemyY);
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
pane.getScene().addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if (key.getCode() == KeyCode.UP) {
controller.getField().getPlayer().setLocation(playerX,playerY-0.1)
// how do I update the player image position inside the canvas?
}
});
}
};
timer.start();
}
您采用了完全错误的方法。 Canvas 中的任何内容一旦绘制完成就无法更新。您可以将其擦除并重新绘制。对于您正在尝试做的事情,场景图更适合。
以下是 mre 演示如何使用向上键在 canvas 上移动图像:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.image.Image;
import javafx.scene.input.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
private static final int SIZE = 200;
private static final String FISH_IMAGE = "https://www.shareicon.net/data/128x128/2015/03/28/14104_animal_256x256.png";
private Image image;
private Canvas canvas;
private final double xPos = 250;
private double yPos = 150;
private static final double MOVE = 0.8;
@Override
public void start(Stage primaryStage) {
image = new Image(FISH_IMAGE,SIZE,SIZE,false,false);
canvas = new Canvas(SIZE*3, SIZE*3);
draw();
Scene scene = new Scene(new StackPane(canvas));
scene.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> animate(key));
primaryStage.setScene(scene);
primaryStage.show();
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
//to avoid multiple handlers do not add handler here
draw();
}
};
timer.start();
}
private void animate(KeyEvent key){
if(key.getCode()== KeyCode.UP) {
yPos -= MOVE;
}
//todo add down, left , right
//for low rate animation, like response to key-press, invoke draw() here instead of using AnimationTimer
}
private void draw(){
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());//clear previous
gc.drawImage(image, xPos, yPos);
}
public static void main(String[] args) {
launch(args);
}
}