Hi guys,
I am looking to create a really simple Javafx game loop and have come up with the following abstract class to extend for the typical iterative method-calls that you would expect from a game-loop. I was just looking for some guidance as to whether this can be improved while still remaining simple?
Ultimately, I still don’t quite understand how the Javafx Canvas and GraphicsContext handles double buffering, will draw calls made in the render method automatically be rendered to the back buffer which is “magically” swapped at the end of the render method, or is this naive and I need to handle this myself?
Is the Animation Timer a good way to go, or should I be opting for the KeyFrame method?
I have tested rendering a few thousand sprites bouncing around on the screen and it appears to work well, I just want to make sure I am not building on top of a bad habit from the start.
public abstract class GameFramework extends Application {
protected Color appBackground = Color.CORNFLOWERBLUE;
protected String appTitle = "Title";
protected int appWidth = 800;
protected int appHeight = 600;
private Canvas canvas;
private GraphicsContext gc;
private Keyboard keyboard;
private Mouse mouse;
private GameLoop gameLoop;
@Override
public void start(Stage stage) {
initialise();
canvas = new Canvas(appWidth, appHeight);
gc = canvas.getGraphicsContext2D();
Group root = new Group();
root.getChildren().add(canvas);
Scene scene = new Scene(root);
keyboard = new Keyboard(scene);
mouse = new Mouse(scene);
stage.setTitle(appTitle);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
gameLoop = new GameLoop();
gameLoop.start();
}
private class GameLoop extends AnimationTimer {
private long before = System.nanoTime();
private float delta;
@Override
public void handle(long now) {
delta = (float) ((now - before) / 1E9);
handleInput(delta);
updateObjects(delta);
gc.setFill(appBackground);
gc.fillRect(0, 0, appWidth, appHeight);
render(gc);
keyboard.poll();
mouse.poll();
before = now;
}
}
protected abstract void initialise();
protected abstract void handleInput(float dt);
protected abstract void updateObjects(float dt);
protected abstract void render(GraphicsContext gc);
}