game101

The Game class

Building a game can be a game itself; or a nightmare. Depending on the tools, the team, the skills, … a lot of thing 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 a 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 a 50 years old man…).

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

Creating a simple class

The basic Game class will support the famous “triptic” 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 from the first ever video game: PONG.

Pong, where all begin !

figure 1 - Pong where all begins (ref:https://fr.wikipedia.org/wiki/Pong)

The original Pong video game from wikipediaAt this very beginning time, the processor to execute tasks is a very a slow on, almost some hundreds of Khz as CPU frequency. To understand the scale we are talking about, current processor are running at 2 to 4 GHz! So processor are very slow, each cycle of CPU is a precious one. So every line of code is very optimized and clearly dedicated to some precise tasks.

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

And swiping the all surface of the screen has a time cost: to display 25 frame per seconds, we need 16ms to swipe a frame. A CRT tube with its ions gun!The CRT Tube is nothing more than a big bubble light. (3) the cathode emits ions (1) and (2) are anodes, deflecting ion ray to screen, lighting a fluorescent dot.

A CRT diagram with ions gun and anodes deflectors

figure 2 - A CRT diagram with ions gun and anodes deflectors

This is the available time for the CPU to prepare 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 basic Game loop explained with a pencil: the method to keep a fixed frame rate !

figure 3 - The basic Game loop explained with a pencil: the method to keep a fixed frame rate !

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

The advanced method to keep a fixed update rate

figure 4 - 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: diagram are largely inspired by the Robert Nystrom book, thanks to him to had shared his own knowledge!

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

A good diagram explaining the Game class and its usage

figure 5 - A good diagram explaining the Game class and its usage

The Game

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 maybe now, the gameloop is the heart of any old school game. and even some Big game engine keep running such old loop. Let’s dive into some details.

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

public class Game {
    //...
    public void loop() {
        int frames = 0;
        int fps = getTargetFps();
        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;
            }
            waitUntilNextFrame(elapsed);
            previousTime = currentTime;
        }
    }

    default void waitUntilNextFrame(double elapsed) {
        try {
            double timeFrame = 1000.0 / getTargetFps();
            int wait = (int) (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();

And when you execute this incredible class… nothing will happen. BUT… we now have the framework of our future game. I’m not joking, this is a fact ;)

Going deeper in concept

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

an overview of the solution:

An overview of my implementation

figure 6 - An overview of my implementation

The Game interface

The Game interface provides a standard contract to any application which want 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 prformed:

but let’s dive in 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 poosible 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 litle wait.

public interface Game {
    //...
    default void loop() {
        int frames = 0;
        int fps = getTargetFps();
        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;
            }
            waitUntilNextFrame(elapsed);
            previousTime = currentTime;
        }
    }

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

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 am not joking, this is a fact ;)

On the next step, nothing more fancy, we will speak about configuration file and CLI parsing, with some real code in a good old GitHub repo. Yes, before going into entertainment, we need to have 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 on this game101 GitHub repository on tag create-game

That’s all folks!

McG.