I'm implementing a simple hockey game following an MVC pattern. I'm having trouble refreshing the player's position, which I have created inside a canvas using the GraphicsContext.drawImage()
method. I'm inside an AnimationTimer
anonymous class, inside the handle
method.
The positions and boundaries are all reflected to the backend,so I don't really need to do any particular logic here, I just want to refresh the player's position on every frame, based on its position calculated inside the model, but I can't access the image I've drawn before in any way. Here's the code:
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();
}
CodePudding user response:
You are following a completely wrong approach. You cannot update anything in a Canvas once it is drawn. You can just erase it and redraw it again. For what you are trying to do the scene graph is much better suited.
CodePudding user response:
The following is an mre demonstrating how to move an image on a canvas using the UP key:
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);
}
}