Game with JDK [1] : a Game

Frederic Delorme
6 min readNov 21, 2022

--

Building a game can be a game itself, or a nightmare. Depending on the tools, the team, the skills, … a lot of things can interact badly with the process of creating a game. And this is exactly what we won’t talk about! :)

Here I will talk about creating an A-B-AB game with the only weapons provided by the nice Java JDK 19 :) And no, I won’t use JavaFX (beuarrk :)) I’ll use the good old AWT and Swing (yes, I am maybe an old 50 years old man…).

Anyway, let’s try it through a series of posts to design some code.

Creating a simple Game class

The basic Game class will support the famous “triptych” of the game loop: manage input, update objects, and draw everything on screen!

But do you know why this is the basic default pattern for a game?

A bit of video game history

Why the game loop exists? This is a very good question and the reason why is a historically based answer. Everything starts with the first-ever video game: PONG.

The original Pong video game from Wikipedia

At this very beginning time, the processor executes tasks very slowly, almost hundreds of Khz as CPU frequency. To understand the scale we are talking about, current processors are running at 2 to 4 GHz!

So processors are very slow, and each cycle of the CPU is a precious one. So every line of code is very optimized and dedicated to some precise tasks.

And another element must be taken into account: the display process. At this time, screens were not flat ones with a bunch of LCDs, but CRT ones. CRT display screens are based on ionic flow starting from a cathode (electronic gun) and moving to the anode (the screen grid) to excite the fluorescent layer in the intern face of the glass bulb.

And swiping all surface of the screen has a time cost: to display 25 frames per second, we need 16ms to swipe a frame.

A CRT tube with its ion gun!

The CRT Tube is nothing more than a big bubble light. (3) the cathode emits ions (1) and (2) are anodes, deflecting ion rays to the screen, and lighting a fluorescent dot.

This is the available time for the CPU to prepare the next image!

So capturing input, moving things, and displaying things must be done in 16ms. And loop again for the next frame.

So the main process is a LOOP. that’s why we talk about a Game Loop:

The method to keep a fixed frame rate

There is also an advanced version of the Game Loop, where multiple updates can be performed between each rendering phase, the timer is around the update methods only:

The advanced method to keep a fixed update rate

I can only invite you to read the fantastic book from Robert Nystrom for details about the Game loop.

Note: diagrams are largely inspired by the Robert Nystrom book, thanks to him to had shared his knowledge!

The Game

Anyway, I need to implement my own. A good diagram is better than a word :

A good diagram explaining the Game class and its usage

And as any tutorial — guide — how-to won’t exist without code; here it is!

public class Game {
public App(String[] args){
initialize(args);
}
//... need to implement some initialization process
public void run(){
create();
loop();
dispose();
}
public void create(){
// create resources for the game.
}
public void loop(){
while(!isExit()){
input();
update();
render();
waitUntilNextFrame();
}
}
public void dispose(){
// will created free resources
}

public static void main(String[] args){
Game game = new App(args);
game.run();
}
}

So, what do you think of my (too?) basic class? nothing fancy, nothing “bling bling”. only useful and mandatory.

So yes, as you may be now, the game loop is the heart of any old-school game. and even some Big game engines keep running such old loops.

Let’s dive into some details.

The Loop is certainly the most important one, so let's get some code:

public void loop(){
double currentTime = System.currentMillis();
double previousTime = currentTime;
double elapsed=0;
while (!iExitRequested()){
currentTime = System.currentMillis();
elapsed = currentTime - previousTime;
input();
update(elapsed);
render();
waitUnitNextFrame(elapsed);
previousTime = currentTime;
}
}

public void waitUntilNextFrame(double elapsed){
try{
int timeFrame = 1000/60;
int wait = elapsed<timeFrame ? timeFrame-elapsed :1;
Thread.sleep(wait);
}catch(InterruptedException ie){
System.err.println("error while trying to wait for sometime");
}
}

So to maintain a sustainable frequency for that loop, I use the default current traditional FPS: 60 frames per second.

So starting with that, defining the waiting time is a simple calculus.

int timeFrame = 1000/60;
int wait = timeFrame - elapsed;

and the rest of the loop process is simple calls:

elapsed = currentTime - previousTime;
input();
update(elapsed);
render();
  • input() will manage all the player’s device input like keyboard, mouse, or joystick,
  • update(elapsed) will compute all the moves and animations for all the game objects,
  • render() will draw the resulting objects and display that on screen.

And when you execute this incredible class… nothing will happen.

Going deeper into the concept

To be sure that this core structure will not be altered by a wrong or bad action from an anonymous developer (??) we are going to externalize this GameLoop and the game structure into an interface.

  • The Game default interface,
  • The App implementing this interface.

an overview of the solution:

An overview of my definitive implementation

figure 1 — An overview of my implementation

The Game Interface

The Game’s interface provides a standard contract to any application which wants to be a game.

Defining a standard lifecycle to a game with:

  1. initialize(),
  2. create(),
  3. and then loop() on the created resources,
  4. and finally dispose() them.
public interface Game {
void initialize(String[] args);
void create(Game g);
void input(Game g);
void update(Game g, double elapsed);
void render(Game g, int fps);
default void loop() {
}
default void run(String[] args) {
initialize(args);
loop();
dispose();
}
void dispose();
boolean isPaused();
boolean isExitRequested();
}

Inside a loop, the 3 historical game operations are performed:

  • input(),
  • update(),
  • render().

but let’s dive into the loop in the default loop implementation.

The loop

The default loop implementation would be a simple time frame-based one. Trying to stick as far as possible to the frame-per-second value set. In our sample code, we use a 1000.0/60.0 frame time corresponding to 60 frames per second.

And during a loop, we call the 3 parts of the loop: manage input(), update() all game objects and render() all of those. And if the loop is during less than a frame time, add a little wait.

default void loop() {
int frames = 0;
int fps = 60;
double internalTime = 0;
double previousTime = System.currentTimeMillis();
double currentTime = System.currentTimeMillis();
double elapsed = currentTime - previousTime;
create(this);
while (!isExitRequested()) {
currentTime = System.currentTimeMillis();
input(this);
elapsed = currentTime - previousTime;
if (!isPaused()) {
update(this, elapsed);
}
render(this, fps);
frames += 1;
internalTime += elapsed;
if (internalTime > 1000.0) {
fps = frames;
frames = 0;
internalTime = 0;
}
if (elapsed < (1000.0 / 60.0)) {
try {
Thread.sleep((int) ((1000.0 / 60.0) - elapsed));
} catch (InterruptedException e) {
Thread.interrupted();
}
}
previousTime = currentTime;
}
}

You can notice that we also compute the real frame rate (fps) with the previousTime and currentTime variables, and maintain an internal frames counter.

Conclusion

BUT… we now have the framework of our future game. I not joking, this is a fact ;)

In the next step, nothing fancier, we will speak about a configuration file and CLI parsing, with some real code in a good old GitHub repo.

Yes, before going into entertainment, we need to have a solid foundation to build upon some fun, and that will come later with some red squares and blue balls moving randomly on the screen.

You will find the corresponding code (and a lot more!) on this GitHub repository https://github.com/SnapGames/game101 on tag create-game

That’s all folks!

McG.

--

--

Frederic Delorme

Platform Architect at BigPharma during days and craftman developer during nights