Hello 64Digits It has been some time since I have created a new blog post. I have decided to start working on my Retro3D engine again I found a lot of things I would like to improve. I am going to start at the beginning and work my way back to where I was and hopefully fix the old issues as I go along.
So my old game loop wasn't that bad actually it performs better than most I have seen out there. I feel that it is good enough to share with the community. So for all you out there trying to create a game engine for your projects take a look and tell me what you think.So the first thing I do that I don't see in most game loop snippets is I use a final AtomicBoolean instead of a volatile boolean. I do this because using an Atomic with synchronization is less likely to cause concurrency issues. You may also notice that while the isRunning method is public the setRunning method is not. This is because no outside class should be calling setRunning directly I have other methods for doing this.private final AtomicBoolean running;
public final boolean isRunning() {
boolean value = false;
synchronized(running) {
value = running.get();
}
return value;
}
private final boolean setRunning(boolean value) {
synchronized(running) {
running.set(value);
}
}
private Thread gameThread;
public final void start() {
if(!isRunning()) {
setRunning(true);
gameThread = new Thread(this);
gameThread.start();
}
}
public final void stop() {
if(isRunning()) {
setRunning(false);
if(!Thread.currentThread().equals(gameThread)) {
while(true) {
try {
gameThread.join();
break;
} catch(Exception exception) {
/* Do Nothing */
}
}
}
}
}
public static final double one_nan = 1000000000;
public static final double max_fps = one_nan / 60;
private final BufferedImage buffer;
@Override
public void paint(Graphics graphics) {
synchronization(buffer) {
graphics.drawImage(buffer, 0, 0, getWidth(), getHeight(), null);
}
}
@Override
public void run() {
long updateEpoch = System.nanoTime();
long renderEpoch = updateEpoch;
while(isRunning()) {
long updateElapse = System.nanoTime() - updateEpoch;
updateEpoch += updateElapse;
update(updateElapse / one_nan);
long renderElapse = updateEpoch - renderEpoch;
if(renderElapse > max_fps) {
synchronization(buffer) {
Graphics2D graphics = buffer.createGraphics();
graphics.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
render(graphics);
graphics.dispose();
}
repaint();
updateEpoch += renderElapse;
}
}
}
public abstract void update(double elapse);
public abstract void render(Graphics2D graphics);