Tag Archives: howto

LWJGL Orthographic Projection

By the end of this tutorial you will have learned how to create and use orthographic projections in the LWJGL.

What is an “orthographic projection”?

An orthographic projection is way of mapping primitives to a canvas. Unlike a perspective projection, an orthographic projection does not give you the illusion of depth. Objects that are far away from the camera will not appear smaller than objects that are close to the camera. It is mainly used to form a rectangle that defines a 2D “camera”. A 2D camera could also be described as a rectangular mask.

How do I create an orthographic projection?

You have actually already created and used an orthographic projection using the glOrtho function. This method multiples the current projection matrix, a fancy name for a “way of mapping primitives to a canvas”, by an orthographic projection that it generates with the given parameters. You set the projection matrix to the orthographic projection by first calling glLoadIdentity and then calling glOrtho.

How should I use glOrtho?

With glOrtho you can construct the previously discussed rectangle by specifying its coordinates. The first and third parameter, left and bottom, specify the coordinates of the bottom-left corner of the camera and the second and fourth parameter, right and top, specify the coordinates of the top-right corner of the camera. The last two parameters are used for 3D projections, but that is beyond the scope of this tutorial.

Examples / Exercises

1. Let’s say you want (0, 0) to be in the top-left corner of the camera and you want (640, 480) to be in the bottom-right corner of the camera. This means that (0, 480) will be in the bottom-left corner and (640, 0) will be in the top-right corner. This is the code you would write before the game loop:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);

2. Now let’s say you want (0, 0) to be in the middle of the camera and you want (1, -1) to be in the bottom-right corner. This means that (-1, -1) will be in the bottom-left corner and (1, 1) will be in the top-right one. This is the code you would write before the game loop:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);

This is, by the way, the default state of the projection matrix (what you get by calling glLoadIdentity).

Questions and remarks

If you didn’t understand something or have questions, please tell me what in the comments. Also, please tell me what you thought about this tutorial.

LWJGL Exporting as JAR

By the end of this tutorial you will have learned about distributing your LWJGL program as a jar-file using JarSplice.

Creating the jar-file containing only the source files

Right click your project in Eclipse and select Export. Select Runnable JAR File and click next. Enter your preferred export location and tick “Copy required libraries … generated JAR”.

Using JarSplice to create a comprehensive jar-file (LWJGL exporting)

Download the JarSplice application here. Open this jar-file by double-clicking on it. Click “Add JARs” and add the previously exported jar-file and the exported jar-file and the library jar-files. Go to “Add Natives” and select all the LWJGL native files. Go to “Main Class” and enter the class – with package definition – containing a main method that you want to execute. Go to “Fat JAR” and select the preferred export location and name.

Testing if it works

Double-clicking on this jar-file should open up your application. If it does not, open the Command Prompt on Windows or the Terminal on Macintosh, and write “java -jar ” followed by the path to the jar-file.

Conclusion

That concludes this tutorial. Should you have any questions or remarks, I would love to see them in the comments section below.

LWJGL Entities

By the end of this tutorial you will have learned how to leverage the power of object-oriented programming to create a game engine containing game entities.

The story behind LWJGL entities

Instead of looking at the scene as a bunch of shapes, look at the scene as a bunch of objects. Each object has material properties, a bounding box for collision and an amount of transparency for instance. Furthermore, each object can be classified into more abstract groups or categories. For example: a football (or soccer ball), a basketball, and a tennis ball are all balls. They all share the same properties of a ball, being round, but they also differ. Utilising this approach makes managing an object pool straightforward.

LWJGL Entity interface

This is the parent interface for the entity.

public interface Entity2D {
	public float getX();
	public float getY();
        public void setX(float x);
        public void setY(float y);
        public void setLocation(float x, float y);
	public void setUp();
	public void destroy();
	public void draw();
}

It is still very basic and generic. Collision detection would be too specific to add here. It would be better to add a CollidableEntity2D down the line.

Abstract classes – being lazy

When a lazy approach is desired, create an abstract class for the aforementioned interface and implement the position methods and leave the remaining methods abstract.

public abstract class AbstractEntity2D implements Entity2D {
	protected float x;
	protected float y;
	public float getX() { return x; }
	public float getY() { return y; }
        public void setX(float x) { this.x = x; }
        public void setY(float y) { this.y = y; }
        public void setLocation(float x, float y) {
    		this.x = x;
    		this.y = y;
        }
	public abstract void setUp();
	public abstract void destroy();
	public abstract void draw();
}

Implementing the interface fully

It is now possible to easily create a class derived from the ‘Entity2D’ interface.

public class Box2D extends AbstractEntity2D {
	protected float size;
	public Box2D(float x, float y, float size) {
		this.x = x;
		this.y = y;
		this.size = size;
	}
	public Box2D() {
		this.x = this.y = this.size = 0;
	}
	@Override
	public void setUp() {
		// We don't need anything here for a box
	}
	@Override
	public void destroy() {
		// We don't need anything here for a box
	}
	@Override 
	public void draw() {
		glBegin(GL_TRIANGLES);
		glVertex2f(x + size/2, y + size/2);
		glVertex2f(x + size/2, y - size/2);
		glVertex2f(x - size/2, y - size/2);
		glVertex2f(x - size/2, y - size/2);
		glVertex2f(x - size/2, y + size/2);
		glVertex2f(x + size/2, y + size/2);
		glEnd();
	}
}

Using the classes for the LWJGL Entities in code

To create an instance of ‘Entity2D’, write the following code.

// Before game loop
Entity2D box = new Box2D(30.0f, 50.0f, 25.0f);
box.setUp();
// In game loop 
box.draw();
// After game loop
box.destroy();

Note that even though the ‘setUp()’ and ‘destroy()’ methods do not appear necessary, they are still called. The reason is that in the future resource handling might be put there.

Conclusion

This concludes this tutorial. Should you have any questions or remarks, I would love to see them in the comments section below.

LWJGL Frame-Rate Independent Movement

By the end of this tutorial you will have learned what frame-rate independent movement is and how you can implement it.

Why use LWJGL frame-rate independent movement?

In 1995 developers wrote their games to run as fast as they possibly could. This worked well when they were working with one machine, but it turned out that every time a faster computer was released, the game suddenly ran a lot faster. This is why the system clock is used to determine how fast the game should run.

How does it work?

Firstly, the system time is stored in a variable of type long called ‘lastFrame’.  Then, in the game loop, the amount of time that has passed since the last frame is retrieved and returned. The code looks like this.

// Under the class definition
private static long lastFrame;
private static long getTime() {
	return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
private static double getDelta() {
	long currentTime = getTime();
	double delta = (double) currentTime - (double) lastFrame;
	lastFrame = getTime();
	return delta;
}
// In initialization code
lastFrame = getTime();
// In game loop
long delta = getDelta();
movement_x += dx * delta;

The delta variable represents the elapsed time since the last frame update. The higher the delta is, the lower the frame-rate will be. The lower the delta is, the higher the frame-rate will be. If the frame-rate is capped to 60 frames-per-second, a delta value lower than 16 should never exist.

Conclusion

This concludes the tutorial for frame-independant movement. Should you have any questions or remarks, put them in the comments section below.

LWJGL Game States

By the end of this episode you will have learned how to implement LWJGL game states.

Why and when are the LWJGL game states used?

To accomplish things like the Skyrim launcher, the main menu in Counter-Strike, or the cinematic when launching Diablo III, the developers use different game states.

Initializing the LWJGL game states

To represent the current game state, an enumerator is used. There are three states: ‘INTRO’, ‘MAIN_MENU’, and ‘GAME’. The code for the enumerator looks like this.

public enum State {
	INTRO, GAME, MAIN_MENU;
}

The program has one static instance of the type State, set by default to the ‘INTRO’ state.

private static State state = State.INTRO;

Rendering the LWJGL game states

To switch over all the possible states, a switch statement is used. Symbolically a colour is assigned to every state. A new method called ‘glRectf(…)’ is also used. This method draws a rectangle with the first and last two parameters being the corners.

switch (state) {
case INTRO:
	glColor3f(1.0f, 0.0f, 0.0f);
	glRectf(0, 0, 640, 480);
	break;
case GAME:
	glColor3f(0.0f, 1.0f, 0.0f);
	glRectf(0, 0, 640, 480);
	break;
case MAIN_MENU:
	glColor3f(0.0f, 0.0f, 1.0f);
	glRectf(0, 0, 640, 480);
	break;
}

The coloured rectangles (quadrilaterals) are just placeholders for things like a Game Menu, an Intro, and a Game Over screen. Post creative and original ideas in the comments.

Input handling

To switch between the different game states, the input is retrieved from the event queue. Insert this code in the game loop.

while (Keyboard.next()) {
	if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
		if(state == State.INTRO)
			state = State.MAIN_MENU;
		else if(state == State.MAIN_MENU)
			state = State.GAME;
		else if(state == State.GAME)
			state = State.INTRO;
	}
}

Conclusion

This concludes the tutorial for game states. As always, should you have any questions or remarks, put them in the comments section below.

Credits

This article was written with the help of Jakob Stein Sturlunson.

LWJGL Textures

By the end of this tutorial you will have learned how to load and display textures.

A quick note

For this tutorial the classes provided by the “slick_util” jar-file will be used.

Loading the LWJGL textures

Firstly, an instance of Texture is created. It is not possible to invoke the constructor of the Texture class, so to initialize the instance, write the following code.

TextureLoader.getTexture(String, InputStream);

This method may throw two exceptions, both of which need to be caught and dealt with.

Texture texture;
try {
	texture = TextureLoader.getTexture("PNG", new FileInputStream(new File("res/image.png")));
        // Replace PNG with your file extension
} catch (FileNotFoundException e) {
	e.printStackTrace();
	Display.destroy();
	System.exit(1);
} catch (IOException e) {
	e.printStackTrace();
	Display.destroy();
	System.exit(1);
}

Drawing the textures

In the upper-left you can see the texture data. Note: “0,1” should be “0,0”. In the bottom-right you can see the shape that uses the texture data.

OpenGL knows where to find its texture data through texture coordinates. Texture coordinates are coordinates ranging from 0.0 to 1.0 ( (0,0) being upper-left; (1,1) being bottom-left ). They represent a point on the texture. Specify a texture coordinate using the following code.

glTexCoord2f(float, float);

In order for OpenGL to know which texture it wants to extract the data from, the texture needs to be bound. Just like with colours, it uses a global state; only one texture can be bound at a time. The binding of textures works with the following method.

glBindTexture(GL_TEXTURE_2D, texture_id);

You can retrieve your texture id from the texture object by calling.

texture.getTextureID();

Similarly, you can unbind a texture from OpenGL when you no longer need to draw with it.

glBindTexture(GL_TEXTURE_2D, 0);

This is how one would draw a textured rectangle on-screen.

glBegin(GL_TRIANGLES);
 
glTexCoord2f(1, 0);
glVertex2i(450, 10);
glTexCoord2f(0, 0);
glVertex2i(10, 10);
glTexCoord2f(0, 1);
glVertex2i(10, 450);
 
glTexCoord2f(0, 1);
glVertex2i(10, 450);
glTexCoord2f(1, 1);
glVertex2i(450, 450);
glTexCoord2f(1, 0);
glVertex2i(450, 10);
 
glEnd();

Releasing the LWJGL textures

Lastly, the texture needs to be destroyed when it’s no longer needed.

texture.release();

Conclusion

That concludes this tutorial. Should you have any questions or remarks I would love to see them in the comments section below.

LWJGL Input

By the end of this tutorial you will have learned how you can receive and process LWJGL input.

Everything is static

Similarly to the Display creation, the Lightweight Java Game Library input API is static.

Polling versus event queue

There are two forms of input handling. Either check the state at the current moment in time (polling) or read events from the event queue. The first method is preferred for movement with the arrow keys or the mouse, while the second method is preferable for when a key is briefly pressed to activate a power-up or click on a menu using the left mouse button.

This graph illustrates the difference between polled and event-driven input. While polled input gives out a signal as long as the button is pressed, the event-driven input only gives out a signal once for every time a button is pressed or released.

Polled LWJGL input

The following code demonstrates polled input.

if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
	player.moveToLeft();
}

Event-driven LWJGL input

The following code demonstrates event-driven input.

while(Keyboard.next()) {
	if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
		jump();
	}
	if (Keyboard.isKeyDown(Keyboard.KEY_F)) {
		pickUpItem();
	}
}

Replace Keyboard with Mouse and ‘isKeyDown’ with ‘isButtonDown’ and the same applies to the mouse input. Use ‘Mouse.getX()’ and ‘Mouse.getY()’ to retrieve the coordinates of the mouse in a non-event-driven style. Similarly, you can use ‘Mouse.getDX()’ and ‘Mouse.getDY()’ to retrieve the displacement over the x-axis or the y-axis. Please note that to retrieve the correct y-coordinate with the projection matrix we created last tutorial, you need to call ‘Display.getHeight() – Mouse.getY() – 1′. If you use ‘Mouse.getDY()’ prefix it by ‘-‘. If this step is omitted, the y-value will be the opposite of the correct value.

Conclusion

That concludes this tutorial. Should you have any questions or remarks, please leave them in the comments section below.

LWJGL OpenGL Drawing

By the end of this tutorial you will have learned how to draw coloured primitive two-dimensional shapes: LWJGL OpenGL drawing.

Immediate mode drawing

In this tutorial I will use the immediate drawing mode. The immediate drawing mode, as well as many other things, was deprecated in OpenGL 3.0, but many of the same principles still apply. This video covers alternate rendering methods.

Where to find the methods

All the OpenGL methods are static. You can find the OpenGL 1.1 methods in the org.lwjgl.opengl.GL11 class. Note that ’11’ stands for version ‘1.1’. Similarly, you can find the methods that were added in OpenGL 1.5 in the org.lwjgl.opengl.GL15 class. If you want to have some documentation, be sure to have a look at the OpenGL 2.1 manual pages.

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

Setting up the projection matrix

The following code initialises a projection matrix where (0,0) is the upper-left corner of the drawing canvas and (640,480) the bottom-right corner of the drawing canvas:

glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Resets any previous projection matrices
glOrtho(0, 640, 480, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);

Clearing the canvas

To clear a 2D drawing canvas, you write:

glClear(GL_COLOR_BUFFER_BIT);

To clear a 3D drawing canvas, you write:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Drawing shapes

You tell OpenGL you want to start rendering by calling:

glBegin(int);

The parameter type is an OpenGL constant. This parameter stands for which shape to draw. IN LWJGL, constants are stored in the form of final integers. You can choose from GL_POINTS, GL_LINES, GL_TRIANGLES, GL_QUADS, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_POLYGONS.

For compliance with modern OpenGL (3.0 and higher), I recommend you avoid GL_QUADS and GL_POLYGONS, as they have been deprecated in OpenGL 3.0.

Each shape requires a set amount of vertices to be drawn. Triangles (GL_TRIANGLES) require three vertices, points (GL_POINTS) require one, and lines (GL_LINES) require two. Once you have sent the required amount of vertices for a shape, the following vertices will be used to assemble the next shape.

Now that OpenGL knows which shape to draw, you can give it the vertex data. Vertex data consists of the positions of the points in the coordinate space, and built-in attributes such as the colour and material.

glVertex(...);

After glVertex you can put a 2, 3, or a 4. This number tells OpenGL how many components the vertex will have. glVertex2 means that the method will take two values, x and y. After this component-indicator you can put an f, a d, or an i. These represent float, double, and integer types respectively. For 2D vertices you often use:

glVertex2f(float, float);

When you are done submitting vertex data to OpenGL, you can stop rendering by writing:

glEnd();

Submitting vertex colours is almost the same as submitting vertex position. Instead of xyzw, colours have rgba, which stand for red, green, blue, and alpha (tranparency). There is a global colour state; once you set the colour to a certain value, it will remain that value until it is changed again. Also, there is no i suffix with colours and, in order to use numerical values, the ub suffix must be used with arguments, typecast to bytes. If a vertex is sent to OpenGL, it links the current colour state to the vertex and draws it accordingly. Colour values for doubles and floats range from 0.0 to 1.0 and for unsigned bytes they range from 0 to 255.

Shapes, front-facing or back-facing?

 

In OpenGL each shape has a front and a back side. Which side is the front-facing one is determined from the order in which you send the vertices and where the camera is located. The side on which the vertices are counter-clockwise, is the front face. The side on which the vertices are clockwise, is the back face. A common performance optimisation known as face culling involves not drawing the back faces of shapes. In 3D this works if the back faces are always on the inside of a shape, and in 2D this works if all the shapes are front-facing.


LWJGL Window

By the end of this tutorial you will have learned how to create, update, and destroy a display compatible with the Lightweight Java Game Library.

Everything is static

Unlike in other Java windowing libraries, the LWJGL handles the window statically. Instead of creating an instance of the hypothetical Display class, static methods are invoked.

Importing classes

Note that Display refers to org.lwjgl.opengl.Display and not the other Display class. Also DisplayMode refers to org.lwjgl.opengl.DisplayMode. The methods that are used in this tutorials are listed below.

Display.setDisplayMode(DisplayMode);
// Sets the display mode (width,height) of the window.
Display.setTitle(String);
// Sets the window title to the specified String.
Display.create();
// Creates a display with the specified display mode and title.
Display.isCloseRequested();
// Returns if the user attempted to close the display.
Display.update();
// Updates the contents of the display and checks for input.
Display.sync(int);
// Caps the frame-rate of the display to the specified amount of frames-per-second.
Display.destroy();
// Frees all the resources allocated for the display and destroys it.

Creating the LWJGL window

Since the method “Display.create()” throws an “LWJGLException”, the try-catch clause will resemble the following.

try {
	Display.setDisplayMode(new DisplayMode(640, 480));
	Display.setTitle("Episode 2 - A fresh display!");
	Display.create();
} catch (LWJGLException e) {
	e.printStackTrace();
	Display.destroy();
	System.exit(1);
}

Updating the window in the game loop

The game loop is a continuous loop in which input handling, game logic, and resource management is done. The loop will be broken if the user requests the display to be closed.

while (!Display.isCloseRequested()) {
	// While no attempt to close the display is made..
	// Put render code here.
	// Put input handling code here.
	Display.update();
	// Refresh the display and poll input.
	Display.sync(60);
	// Wait until 16.67 milliseconds have passed. (Maintain 60 frames-per-second)
}

Destroying the LWJGL window

After the game loop has been broken, the resources have to be cleaned up. In this case of this program, the only thing that needs to be cleaned up in the display itself.

Display.destroy();

For some inexplicable reason the window does not immediately close when the user clicks on the close button – it lingers for several seconds. Fixing this consists of placing the following line after “Display.destroy();”.

System.exit(0);

This quits the Java Virtual Machine. Keep in mind that any code written after this will not be executed.

Entire source code

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.LWJGLException;
 
public class YourFirstDisplay {
	public static void main(String[] args) {
		try {
			Display.setDisplayMode(new DisplayMode(640, 480));
			Display.setTitle("A fresh display!");
			Display.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
			Display.destroy();
			System.exit(1);
		}
		while(!Display.isCloseRequested()) {
			Display.update();
			Display.sync(60);
		}
		Display.destroy();
		System.exit(0);
	}
}

Conclusion

That concludes this tutorial. If you have any questions please leave a comment below.

LWJGL Workspace

Click to watch the corresponding video on YouTube.

By the end of this tutorial you will have learned how to set up the LWJGL workspace for compiling and running LWJGL programs.

Downloading the required files

Download the latest version of the LWJGL here and the latest version of the “slick_util” jar-file here. Extract the downloaded zip-file and put all the files and folders in one directory. To install Eclipse, download the “Classic” or “IDE for Java Developers” version here. Put the downloaded Eclipse folder in a directory to which you have read and write permissions (i.e. not in Program Files or Applications).

Creating a project in the LWJGL workspace

Click the Eclipse executable. Select a Workspace folder, in which all your Java projects will be stored. Go to the menu “File”, “New”, click on “Java Project” and enter a name for the LWJGL project. The project files will be stored in the previously specified workspace folder.

Adding the library files

Open the project directory containing the “src” and “bin” directories. Add a directory called “lib” containing two subsequent directories called “natives” and “jars”. The project directory should now contain the following folders.

- lib
- src
- bin
- lib/natives
- lib/jars

Move the “lwjgl.jar” and “lwjgl_util.jar” files from the extracted zip-file and the “slick_util.jar” file to the “lib/jars” directory. Move the native files applicable to the current Operating System found in the zip-file to the “lib/natives” directory.

This is how the project folder should look.

Linking the jar files and the natives

Open Eclipse. Go to the menu “File” and click “Refresh”. Right-click on the previously created Eclipse project and click on “Properties”. Go to “Java Build Path” and select the “Libraries” tab. Click “Add JARs…” and select the “slick_util.jar”, “lwjgl.jar”, and “lwjgl_util.jar files. Expand the lwjgl.jar list item and double-click “Native Library Folder Configuration”.  Write the name of your project followed by “/lib/natives” and click “OK”.

Project Properties

This is what the Java Build Path window in Eclipse should resemble. (The “slick_util” jar-file should also be there.)

Testing the configuration

To test if it actually works copy the following code into your project and run it. In the case of no exceptions and the display of a window, the configuration has been set up correctly.

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
 
/**
 * If this application shows a blank and responsive window
 * and doesn't throw any errors, you know you have installed lwjgl
 * correctly.
 * @author Oskar Veerhoek
 */
public class DisplayTest {
    public static void main(String[] args) {
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Episode 1 – Display Test");
            Display.create();
        } catch (LWJGLException e) {
            System.err.println("Display wasn't initialized correctly.");
            System.exit(1);
        }
 
        while (!Display.isCloseRequested()) {
            Display.update();
            Display.sync(60);
        }
 
        Display.destroy();
        System.exit(0);
    }
}

java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path

This exception is thrown when LWJGL cannot find the native files it needs. Perhaps the natives file path has been set up incorrectly or the native files for another Operating System were selected.

Conclusion

That concludes this tutorial. Should you have any questions or remarks, leave them in the comments.