LWJGL 2D Breakout Tutorial – Slick2D and images

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

This is the third post in a series. You should probably go back and start from the first post. LWJGL 2D Breakout Tutorial – Environment Setup

Ok, so we’ve got a shape drawing, but I really want to draw *images*. Luckily, we spent all that time setting up the slick2D dependency, so it should be a piece of cake!

First we need to include our new dependencies in our App.java file.

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
import org.newdawn.slick.Color;

And… well, shoot. It looks like something’s wrong with the Slick2D dependency inclusion, because all of those are yelling about an error.

Ah, I see what the problem is; I told you to include the wrong dependency in your pom.xml file. The new slick dependency should be:

<dependency>
	<groupId>org.slick2d</groupId>
	<artifactId>slick2d-core</artifactId>
	<version>${slick.version}</version>
</dependency>

So we need to copy that other compiled .jar from the slick2d repo that we ran before. So copy slick2d-core-2013.08-SNAPSHOT.jar from ~/.m2/repository/org/slick2d/slick2d-basic-game-archetype/ into our project’s repo file, and remove the old jar that was there.

cp ~/.m2/repository/org/slick2d/slick2d-basic-game-archetype/slick2d-core-2013.08-SNAPSHOT.jar ~/git/breakout-lwjgl/breakout/repo/

Great! Now our dependencies should all be working and… wait a minute… Now I’m getting a dependency error saying we’re missing javax.jnlp api. Ugh. So there’s a problem with all of this, and that’s you can only get the jnlp from javaws.jar. That’s a problem because that jar file is ONLY found in the oracle version of java. Ok, so we need some major changes to our environment to make this work. Sorry guys.

sudo apt-get install oracle-java7-installer

Ok, now we need to recompile our slick2d project with the new library.

export JAVA_HOME='/usr/lib/jvm/java-7-oracle/'
cd ~/git/slick2d-maven
mvn clean package

and copy it back to our repo…

cp ~/git/slick2d-maven/slick2d-core/target/slick2d-core-2013.08-SNAPSHOT.jar ~/git/breakout-lwjgl/breakout/repo/

And now our slick2d dependency is up to date. So now we need to modify our pom.xml file to reflect our new dependencies and where we get them from.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>breakout-lwjgl</groupId>
	<artifactId>breakout</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>breakout</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<natives.version>0.0.6</natives.version>
		<lwjgl.version>2.8.4</lwjgl.version>
		<slick.version>2013.08-SNAPSHOT</slick.version>
		<junit.version>4.10</junit.version>
	</properties>

	<repositories>
		<repository>
			<id>mavenNatives</id>
			<name>Maven Natives Repository</name>
			<url>http://mavennatives.googlecode.com/svn/repo</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>slick2d</id>
			<name>Slick2D</name>
			<url>file:${project.basedir}/repo</url>
		</repository>
	</repositories>

	<pluginRepositories>
		<pluginRepository>
			<id>central</id>
			<name>Maven Plugin Repository</name>
			<url>http://repo1.maven.org/maven2</url>
			<layout>default</layout>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
			<releases>
				<updatePolicy>never</updatePolicy>
			</releases>
		</pluginRepository>
	</pluginRepositories>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.jnlp</groupId>
			<artifactId>jnlp-api</artifactId>
			<version>7.0</version>
			<scope>system</scope>
			<systemPath>${java.home}/lib/javaws.jar</systemPath>
		</dependency>
		<dependency>
			<groupId>org.lwjgl.lwjgl</groupId>
			<artifactId>lwjgl</artifactId>
			<version>${lwjgl.version}</version>
		</dependency>
		<dependency>
			<groupId>org.slick2d</groupId>
			<artifactId>slick2d-core</artifactId>
			<version>${slick.version}</version>
		</dependency>
		<dependency>
			<groupId>java3d</groupId>
			<artifactId>vecmath</artifactId>
			<version>1.3.1</version>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<configuration>
						<source>1.6</source>
						<target>1.6</target>
					</configuration>
				</plugin>

				<plugin>
					<groupId>com.googlecode.mavennatives</groupId>
					<artifactId>maven-nativedependencies-plugin</artifactId>
					<version>${natives.version}</version>
					<executions>
						<execution>
							<id>unpacknatives</id>
							<phase>generate-resources</phase>
							<goals>
								<!--suppress MavenModelInspection (this line is for IDEA) -->
								<goal>copy</goal>
							</goals>
						</execution>
					</executions>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-dependency-plugin</artifactId>
					<executions>
						<execution>
							<id>copy-dependencies</id>
							<phase>package</phase>
							<goals>
								<goal>copy-dependencies</goal>
							</goals>
							<configuration>
								<outputDirectory>${project.build.directory}</outputDirectory>
								<overWriteReleases>false</overWriteReleases>
								<overWriteSnapshots>true</overWriteSnapshots>
							</configuration>
						</execution>
					</executions>
				</plugin>
				<plugin>
					<artifactId>maven-assembly-plugin</artifactId>
					<configuration>
						<archive>
							<manifest>
								<addClasspath>true</addClasspath>
								<mainClass>breakout_lwjgl.breakout.App</mainClass>
							</manifest>
						</archive>
						<descriptorRefs>
							<descriptorRef>jar-with-dependencies</descriptorRef>
						</descriptorRefs>
					</configuration>
					<executions>
						<execution>
							<id>make-assembly</id>
							<phase>package</phase>
							<goals>
								<goal>single</goal>
							</goals>
						</execution>
					</executions>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

*sighs* You have no idea how long it’s taken me to figure this out. Also, if you notice any extraneous or incorrect elements in the future, please let me know.

So now we’ve got our updated dependencies, a fresh new oracle-java-7 install and a pom.xml file that should set everything up correctly. But Eclipse is still complaining. So we need to adjust our project settings.

project_propertiesnative_library_location_correctadd_library_add_jrealternate_jre_installed_jresadd_standard_vmjre_definition_add_external_jarsadd_javaws_jarswitch_to_java_7

At this point I found it necessary to restart eclipse so that my dependencies would take effect, but that might vary per environment. Doesn’t hurt, at least.

FINALLY! Now I am seeing no red warnings anywhere, so lets go ahead and finish up our code.

package breakout_lwjgl.breakout;

import java.io.IOException;

import javax.vecmath.Vector2f;

import org.lwjgl.input.Keyboard;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
import org.newdawn.slick.Color;

public class App {

	public boolean[] keysPressed = new boolean[255];
	public Vector2f ballPosition = new Vector2f();
	public Texture ballTexture;

	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.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glOrtho(0, 800, 600, 0, -1.0f, 1.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);

		try {
			this.init();
		} catch (IOException e) {
			e.printStackTrace();
		}

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

		Display.destroy();
	}

	public void init() throws IOException {
		this.ballPosition.x = 50;
		this.ballPosition.y = 50;

		this.ballTexture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/fire_ball.png"));
	}

	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.ballPosition.x -= 1.0;
		}
		if (this.keysPressed[Keyboard.KEY_RIGHT]) {
			this.ballPosition.x += 1.0;
		}
		if (this.keysPressed[Keyboard.KEY_UP]) {
			this.ballPosition.y -= 1.0;
		}
		if (this.keysPressed[Keyboard.KEY_DOWN]) {
			this.ballPosition.y += 1.0;
		}
	}

	public void draw() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		Color.white.bind();
		this.ballTexture.bind();

		GL11.glBegin(GL11.GL_QUADS);
		GL11.glTexCoord2f(0, 0);
		GL11.glVertex2f(this.ballPosition.x, this.ballPosition.y);
		GL11.glTexCoord2f(1, 0);
		GL11.glVertex2f(this.ballPosition.x + this.ballTexture.getTextureWidth(), this.ballPosition.y);
		GL11.glTexCoord2f(1, 1);
		GL11.glVertex2f(this.ballPosition.x + this.ballTexture.getTextureWidth(), this.ballPosition.y + this.ballTexture.getTextureHeight());
		GL11.glTexCoord2f(0, 1);
		GL11.glVertex2f(this.ballPosition.x, this.ballPosition.y + this.ballTexture.getTextureHeight());
		GL11.glEnd();

		Display.update();
	}

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

That’s the whole App.java file now. Note that we had to modify the OpenGL settings to support 2d textures and alpha channels (since we’re going to use a PNG).
Also, now instead of defining our poly size, we’re letting the size of the texture do that for us. So now pick a friendly PNG texture (I used a ball from a breakout game I’ve made previously) and put it into a folder called “res” in your project.
project_with_res

fire_ball

Now right click on the project and go to Run As -> Maven clean
maven_clean

You also might need to redo the native dependencies, so navigate to your project folder in the terminal and type

mvn nativedependencies:copy

if you don’t have them.

Then run maven install and everything should go smoothly. If it doesn’t at this point, send me a message or leave a comment! I learned a ton debugging these issues over the last several days so please ask for help instead of crying in your beer. Not that I did that.

With this, our project should be entirely set up and compiling with all it’s fancy dependencies… so let’s run it. Press the green Run App button in eclipse, and try out your fancy new moving image.

moving_ball_in_game

Advertisements
LWJGL 2D Breakout Tutorial – Slick2D and images

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