LWJGL 2D Breakout Tutorial – OpenGL drawing and keyboard input

Update: Just trying to get set up? Check out the streamlined setup tutorial LWJGL 2D Breakout Tutorial – Setup Summary.

This is the second post in a series, you should probably go back and read the first post. LWJGL 2D Breakout Tutorial – Environment Setup

Ok, so we were able to run our Hello World project that Eclipse created for us, but that’s not really anywhere close to making a game. So let’s make a window!

package breakout_lwjgl.breakout;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

public class App {
	public void start() {
		try {
			Display.setDisplayMode(new DisplayMode(800, 600));
			Display.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
			System.exit(0);
		}
		
		while (!Display.isCloseRequested()) {
			Display.update();
		}

		Display.destroy();
	}

	public static void main(String[] argv) {
		App displayExample = new App();
		displayExample.start();
	}
}

Sweet! Ok, let’s run this.

app_window_failure

Oh… that’s no good. I thought we had our environment set up correctly. It looks like it can’t find the libraries. We need to get the native local libs so we can run on my current machine. Luckily, we have maven! Open a terminal and navigate to your project location.

mvn nativedependencies:copy

This will find and copy all of the native libs we need to actually run a LWJGL project. But remember, running a maven clean after this will result in these files being deleted. You’ll have to copy them over again if you do a clean. (I wonder if there’s an easy way to automate this…)

Run maven install on your project through Eclipse, and when it’s completed, give it another try.

It’s alive! We have a LWJGL game window running and ready for our awesome code! So… what now? Let’s draw something. How about a square? We can use OpenGL to do this. Let’s add the import for it (import org.lwjgl.opengl.GL11) at the top and then put in some OpenGL code.
Replace the while loop in the previous code with this.

GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, 800, 600, 0, -1.0f, 1.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);

		while (!Display.isCloseRequested()) {
			GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

			GL11.glColor3f(0.4f, 1.0f, 0.4f);

			GL11.glBegin(GL11.GL_QUADS);
			GL11.glVertex2f(50, 50);
			GL11.glVertex2f(150, 50);
			GL11.glVertex2f(150, 150);
			GL11.glVertex2f(50, 150);
			GL11.glEnd();

			Display.update();
		}

little_green_square

Neat! It’s a little green square! Note here that I’m doing some things that will make 3D work a little tricker. But since I’m working on a 2D breakout for right now, this shouldn’t really matter.

In particular, I have set the ortho view to invert the y axis, so that the things I draw will have the top-left corner set to 0,0.

GL11.glOrtho(0, 800, 600, 0, -1.0f, 1.0f);

Ok, so a square is cool and all… but what about moving it around? Can it respond to the keyboard? Piece of cake! But now we’re getting into code and design philosophies, and I have a pretty strong opinion here. It is VERY ESSENTIAL to being programming your game with your drawing code and your update code COMPLETELY SEPARATE. Things could get messy the more complex your game is, and tracking down a bug where the user can only collide with something when he’s facing a particular direction is a nightmare to debug that I would never wish on anyone. So keep your logic and drawing code separate.

Here’s my updated version, with a few more functions to begin separating things out.

package breakout_lwjgl.breakout;

import javax.vecmath.Vector2f;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class App {
	
	public boolean[] keysPressed = new boolean[255];
	public Vector2f squarePosition = new Vector2f();
	public Vector2f squareSize = new Vector2f();
	public void start() {
		try {
			Display.setDisplayMode(new DisplayMode(800, 600));
			Display.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
			System.exit(0);
		}
		
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0, 800, 600, 0, -1.0f, 1.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		
		this.init();

		while (!Display.isCloseRequested()) {
			this.update();
			this.draw();
		}

		Display.destroy();
	}
	
	public void init() {
		this.squarePosition.x = 50;
		this.squarePosition.y = 50;
		this.squareSize.x = 100;
		this.squareSize.y = 100;
	}
	
	public void update() {
		while(Keyboard.next()) {
			if(Keyboard.getEventKeyState()) {
				this.keysPressed[Keyboard.getEventKey()] = true;
			} else {
				this.keysPressed[Keyboard.getEventKey()] = false;
			}
		}
		
		if(this.keysPressed[Keyboard.KEY_LEFT]) {
			this.squarePosition.x -= 1.0;
		}
		if(this.keysPressed[Keyboard.KEY_RIGHT]) {
			this.squarePosition.x += 1.0;
		}
		if(this.keysPressed[Keyboard.KEY_UP]) {
			this.squarePosition.y -= 1.0;
		}
		if(this.keysPressed[Keyboard.KEY_DOWN]) {
			this.squarePosition.y += 1.0;
		}
	}
	
	public void draw() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

		GL11.glColor3f(0.4f, 1.0f, 0.4f);

		GL11.glBegin(GL11.GL_QUADS);
		GL11.glVertex2f(this.squarePosition.x, this.squarePosition.y);
		GL11.glVertex2f(this.squarePosition.x + this.squareSize.x, this.squarePosition.y);
		GL11.glVertex2f(this.squarePosition.x + this.squareSize.x, this.squarePosition.y + this.squareSize.y);
		GL11.glVertex2f(this.squarePosition.x, this.squarePosition.y + this.squareSize.y);
		GL11.glEnd();

		Display.update();
	}

	public static void main(String[] argv) {
		App displayExample = new App();
		displayExample.start();
	}
}

This version has split out the init step, and then will call update before it calls draw. This means we have a chance to listen to input and update parameters every single frame.

Check out the next post in this series: LWJGL 2D Breakout Tutorial – Slick2D and images

Advertisements
LWJGL 2D Breakout Tutorial – OpenGL drawing and keyboard input

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s