Josh H.
Josh H.

Reputation: 1

Updating and rendering for a 2D game in Java

So, I am working on making a 2D game in Java, and I really don't have too much experience with Java. I currently use a very simple loop using a swing timer running every 10ms or so that looks something like:

public void actionPerformed(ActionEvent e) {
update();
repaint();
}

However, I need something more practical for obvious reasons. These reasons include the fact that more lag means less FPS AND slower movement/other updating. I found the following code in a tutorial for a 3D Java game here. It would begin running when the program starts, and I understand enough to know it would work. However, I do not fully understand it: (tick() is the updater, render() renders the screen)

    long currenttime;
    long previoustime = System.nanoTime();
    long passedtime;
    int frames = 0;
    double unprocessedseconds = 0;
    double secondspertick = 1 / 60.0;
    int tickcount = 0;
    boolean ticked = false;     

    while (gameIsRunning) {
        currenttime = System.nanoTime();
        passedtime = currenttime - previoustime;
        previoustime = currenttime;
        unprocessedseconds += passedtime / 1000000000.0;

        while (unprocessedseconds > secondspertick) {
            tick();
            unprocessedseconds -= secondspertick;
            ticked = true;
            tickcount++;
            System.out.println(tickcount);
            if (tickcount % 60 == 0) {
                System.out.println(frames + " FPS");
                previoustime += 1000;
                frames = 0;
            }
        }
        if (ticked) {
            render();
            frames++;
        }
        render();           
        frames++;
    }

This code was not explained in the tutorial I found it in. Could someone please break this down and explain it? I have also looked here for ideas, and the final piece of code on that page with a render thread and an update thread makes a lot of sense to me. Which method should I use? One of the above, or something totally different? Also, you can probably tell that this is my first question here on stackoverflow. Thanks in advance, Josh

Upvotes: 0

Views: 8028

Answers (2)

user3470702
user3470702

Reputation: 7

The way I do my engines is just as explained before, I multi-thread. Basically, if you split the job of processing and drawing the game into two segments it becomes quicker at the expense of more resources in use. I do a little something like this:

public class Engine implements Runnable {

    //Sets classes
    Engine tick = new Engine(true);
    Engine render = new Engine(false);
    Thread tickThread = new Thread(tick);
    Thread renderThread = new Thread(render);

    boolean job;
    boolean isRunning = false;

    long sleepTime = 5L;

    public Engine(boolean job) {
         //Sets what the thread does
         this.job = job;
    }

    public static void startEngine() {
         //Starts Engine
         isRunning = true;
         tickThread.start();
         renderThread.start();
    }

    public void tick() {
         //Process things
    }

    public void render() {
         //Draw things
    }

    public void run() {
         //Do engine base things
         while(isRunning) {
              if(job) {
                   tick();
              } else {
                   render();
              }
              Thread.sleep(sleepTime);
         }
    }

}

This is by no means advanced. This is just an example of what a simple multi-thread game engine would be like. Honestly, I used this exact code when I was starting off making games. This could be used but some adjustments should be made depending on what you use it for. What I mean is that lets say you have an object that's moving and its being rendered at the same time. If the objects position is 50 and increasing and the render method is drawing it then the object could go to 51 then 52 before being rendered again. Normally, the processing is faster than the drawing. Another example: Lets say you have an ArrayList and are constantly removing and adding objects to it. Sometimes you can remove an object just as the render method is about to draw it and cause a null pointer exception because it's trying to draw something that doesn't exist. (I used "if(object.get(i) != null)" and worked around it that way) I hope this helped at least a little (two years later, lol) and helped you get a basis of what multi-threading is like (if you didn't already).

Upvotes: 0

William Morrison
William Morrison

Reputation: 11006

tick() is probably updating the game object's physical properties (position, velocity, etc.) tick() is called multiple times each update because some simulations can't handle too large a timestep without becoming unstable.

There's a popular article online which explains why this is the case, and why using a fixed timestep is the proper procedure. Check it out.

Each update the game is advanced in 1/60th second (so 60 frames a second) increments. This is repeated until there's less than 1/60th a second remaining in the aggregate. Aggregate is just a fancy word for sum.

Then a snapshot of the game's current state is rendered to the screen.

I won't get too deep into it, but really this code should be inerpolating each object's position by the remaining time in the aggregate during render().

long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
//this is an aggregate, games usually step in fixed units of time.
//this is usually because physics simulations can't handle too large of time steps.
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;     

while (gameIsRunning) {
    //get elapsed nano seconds from the epoch (january 1st, 1970)
    currenttime = System.nanoTime();
    //take difference of current time in nanos and previous time in nanos
    passedtime = currenttime - previoustime;
    previoustime = currenttime;
    //divide to get the elapsed time in seconds.
    unprocessedseconds += passedtime / 1000000000.0;

    while (unprocessedseconds > secondspertick) {
        tick();
        unprocessedseconds -= secondspertick;
        ticked = true;
        tickcount++;
        System.out.println(tickcount);
        if (tickcount % 60 == 0) {
            System.out.println(frames + " FPS");
            previoustime += 1000;
            frames = 0;
        }
    }
    if (ticked) {
        render();
        frames++;
    }
    render();           
    frames++;
}

Good luck Josh.

Edit:

I have no experience with games using one thread for updates, and one for rendering. I can't give advice on those for that reason. If you have little or no experience with multithreading I'd avoid it as only complex games are likely to require this approach, and multithreading will add a multitude of issues you probably don't want to deal with.

Multithreaded game engines will consume more memory between rendering and updating than a single threaded game, or will wind up being depend on one another anyway. This is because the two threads can't manipulate the same data simultaneously. Therefor the only way for the two threads to operate is with synchronization on those data structures, or by the update thread suppling the render thread with immutable data to render.

Writing a multithreaded game engine would be a good introduction to threading. It could teach you quite a lot. Depends on what you want to get out of this.

If you are making a 2D game I feel even more confident that you will not need one thread for updating and one for rendering.

If you really want to pursue this, here's the approach I'd take.

You don't need more than a while loop to control rendering.

Upvotes: 1

Related Questions