Game Loop with LWJGL

Hello,

I’ve been trying for a good while to write a game loop, but with no success. The framerate is usually inconsistent and occasionally stutters/jumps. Originally I was writing code using Java 2D until I realized that the stuttering was unbearable and caused by lack of V-sync. So I decided to switch over to LWJGL with the promise of a better stutter free framerate. Even though the stuttering did subside a bit, I still was noticing it. I’ve been using the most popular articles on game loops as a guide, but I’m still having trouble applying it to Java.

http://lspiroengine.com/?p=378
https://gafferongames.com/post/fix_your_timestep/

I wrote an example application to show how I’m doing things. I just don’t know what to do at this point, and any advice would be helpful.

 import java.awt.Color;

    public class GameEngine extends GameCore {
        
        public static void main(String[] args) {
        	
        	GameEngine game = new GameEngine();
        	
    		if(!game.initGame(640, 480, "Game Test")) {
    			return;
    		}
    		
    		game.startExecution();
        }
        
        protected void init() {
        	
        }
        
        int prex, curx;
    	protected void update() {
    		prex = curx;
    		
    		curx += 5;
    		
    		if(curx >= 480) {
    			prex = 0;
    			curx = 0;
    		}
    	}
    	
    	protected void render(GraphicsContext gc, float delta) {
    		
    		float x = (int)(prex + (curx - prex) * delta);
    		
    		gc.setColor(Color.RED);
    		gc.fillRect4f(x, x, 64, 64);
    		
    	}
    }



import org.lwjgl.opengl.GL;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.system.MemoryUtil.NULL;

public abstract class GameCore {
	
	protected long window;
	protected GraphicsContext gc;
	
	public boolean initGame(int w, int h, String title) {
		
		// WINDOW //
		if(!glfwInit()) {
			return false;
		}
		
		window = glfwCreateWindow(w, h, title, NULL, NULL);
		
		if(window == NULL) {
			glfwTerminate();
			return false;
		}
		
		glfwMakeContextCurrent(window);
		GL.createCapabilities();
		
		glEnable(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, w, 0, h, 0, 1);
		
		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		
		glfwSwapInterval(1);
		
		// GRAPHICS CONTEXT //
		gc = new GraphicsContext();
		gc.setViewHeight(h);
		
		// INIT //
		init();
		
		return true;
	}
	
	public void startExecution() {
		
		double udelay     = 1.0d / 30.0d;
		double upoint     = 0.0d;
		
		double stime      = glfwGetTime();
		double ctime      = 0;
		
		while(!glfwWindowShouldClose(window)) {
			
			ctime = glfwGetTime() - stime;
			
			while((ctime - upoint) >= udelay) {
				upoint += udelay;
				update();	
			}
			
			glClear(GL_COLOR_BUFFER_BIT);
			renderMain( (float)((ctime - upoint) / udelay) );
			glfwSwapBuffers(window);
				
			glfwPollEvents();
		}
		
		glfwDestroyWindow(window);
		glfwTerminate();
	}
	
	private void renderMain(float delta) {
		
		gc.renderBegin();
		render(gc, delta);
		gc.renderEnd();
	}
	
	protected abstract void init();
	protected abstract void update();
	protected abstract void render(GraphicsContext gc, float delta);
}


import java.awt.Color;

import static org.lwjgl.opengl.GL12.*;

public class GraphicsContext {
	
	protected int viewh;
	
	public GraphicsContext() {
		
	}
	
	public void renderBegin() {
		glBegin(GL_TRIANGLES);
	}
	
	public void renderEnd() {
		glEnd();
		glFlush();
	}
	
	public void setViewHeight(int vh) {
		viewh = vh;
	}
	
	public void setColor(Color c) {
		glColor4f(c.getRed() / 255.0f, c.getGreen() / 255.0f, 
				  c.getBlue() / 255.0f, c.getAlpha() / 255.0f);
	}
	
	public void fillRect(int x, int y, int width, int height) {
		drawQuad(x, y, x + width, y + height);
	}
	
	public void fillRect4f(float x, float y, float width, float height) {
		drawQuad(x, y, x + width, y + height);
	}
	
	public void drawQuad(float x1, float y1, float x2, float y2) {
		
		// Convert the coordiates from Java 2D to Opengl coordinate system.
		y1 = viewh - y1;
		y2 = viewh - y2;
		
		// Render the quad as two triangles.
		
		// Top-Left Triangle 
		glVertex2f(x1, y1);
		glVertex2f(x2, y1);
		glVertex2f(x1, y2);
		
		// Bottom-Right Triangle 
		glVertex2f(x2, y2);
		glVertex2f(x2, y1);
		glVertex2f(x1, y2);
	}
}

Thanks!

You need to draw using OpenGL 4+ shaders, not using outdated constructs.

Here’s a good channel to explore https://www.youtube.com/user/ThinMatrix/playlists