Using SConS to build and release a Java/Slick Game


Richard Marks:
Using SConS to build and release a Java/Slick Game

Scrim had trouble releasing his game that he created with Java and the Slick library.
He was using Eclipse to build his project, and I informed him that it has been my experience that Eclipse is a horrible build solution, and that I use SConS.

I am here to explain how I solved his problems. (He in fact had multiple when he thought he had only one)
I hope that this article helps anyone else who may have similar troubles.

Since I was going to use SConS and not Eclipse to build his project, I had to write a SConstruct file to do this.


# SConstruct JAVA build script for LofiWanderings
buildEnv = Environment(
appClasses = buildEnv.Java('.', 'src')
buildEnv.Jar('release/LofiWanderings.jar', appClasses + ['MANIFEST.MF', 'resources'])

It is a very simple script.
First we setup the building-environment variable buildEnv. I called it buildEnv to make it clear what it is.
We need to tell our build environment where to find the external libraries that we are using.
We do this by setting the JAVACLASSPATH and JAVACLASSDIR to point to our external library JAR files.

Next we create a list of the names of the compiled .class files and store them in the appClasses variable.
The files are compiled by the buildEnv.Java('.', 'src') command which says place the compiled classes in the current directory, and find the .java sources in the src directory in the current directory.

This compiles all the .java source files in the src/ directory and places the compiled .class files in the current directory.
The .java files are written as packages, so the .class files are automatically placed in the fully-qualified directory com/scrimisms/LofiWanderings/

Next thing we do is we create our JAR file with the command:

buildEnv.Jar('release/LofiWanderings.jar', appClasses + ['MANIFEST.MF', 'resources'])

Which says that we want our JAR to be created in the release/ directory in the current directory.
The files to be placed in the JAR file are all .class files and the MANIFEST.MF file, and the resources/ directory.

Here is the MANIFEST.MF file:

Manifest-Version: 1.0
Created-By: Scrim
Main-Class: com.scrimisms.LofiWanderings.MapMain
Class-Path: lib/slick.jar lib/lwjgl.jar

Take note that you MUST have a new-line at the end of the last line!
Otherwise the line WILL be ignored, and your jar will not function!

Lets have a look now at the project directory tree before we run SConS:


resources/ (I'm omitting the list of resource files to be brief)
src/com/scrimisms/LofiWanderings/ (list of .java source files omitted to be brief)

In your terminal, in the project directory, type "scons"


$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
javac -classpath lib/slick.jar:lib/lwjgl.jar -d . -sourcepath src src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/ src/com/scrimisms/LofiWanderings/
jar cfm release/LofiWanderings.jar MANIFEST.MF com/scrimisms/LofiWanderings/ArtManager.class com/scrimisms/LofiWanderings/GameState.class com/scrimisms/LofiWanderings/Map.class com/scrimisms/LofiWanderings/MapMain.class com/scrimisms/LofiWanderings/MapView.class com/scrimisms/LofiWanderings/Position.class com/scrimisms/LofiWanderings/WallSpriteSet.class resources
scons: done building targets.

You will gain 2 new top-level directories in the current directory:

com/scrimisms/LofiWanderings/ (I told you before that SConS will create the fully-qualified path to the .class files)

The release directory is where your new JAR file is located.

So now that you know what you need to have to BUILD the project; lets continue on to Scrim's problems. ;D

First his problem as was stated to me:

02/03/09 10:35:47 PM [0x0-0xf16f16][61706] Exception in thread "main" java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path

This is cryptic to anyone who is new to using external libraries in java (like I was).
What the error means is that the native library lwjgl cannot be found.

I stressed over this issue for about 5 hours before understanding that it had nothing to do with java!
The answer to solving this problem was for the lwjgl native libraries to be on the SYSTEM PATH!
I solved this by simply placing the native library files in the same folder as the .jar file.

The release folder now looks like this:


And so I then ran the JAR:

$ java -jar LofiWanderings.jar

And I was hit with a bunch of errors that started with:

java.lang.RuntimeException: Resource not found:

So I knew that something was up.
I looked at his .java sources and noticed that he was not specifying the correct path to his resources!
I added the "resources/" part to his paths in his code, and rebuilt the project with SConS again.
Running it again I then got new errors:

Tue Mar 03 12:28:40 CST 2009 WARN:class org.newdawn.slick.opengl.PNGImageData failed to read the data
Tue Mar 03 12:28:40 CST 2009 WARN:class org.newdawn.slick.opengl.ImageIOImageData failed to read the data

I suspected that the PNG files were corrupt.
I jump in the resource directory and check the file types:

$ cd ../resources/first_wall/
$ find . -name "*.png" | xargs identify

Sure enough... the files were NOT PNG files at all!


TIFF 252x336 252x336+0+0 DirectClass 8-bit 334.912kb

Bingo. Ok, needed to fix that.

Easy enough.. from the resources/ directory we do this:


$ find . -name "*.png" | rename s/png/tif/g
$ for i in `find . -name "*.tif"`; do convert "$i" "$i".png; done
$ find . -name "*.tif.png" | rename s/tif\.//g
$ find . -name "*.tif" | xargs rm

Okay, that is some linux black-magic there;  8) but I'll explain it.

Line #1 - rename all the .png files to .tif
Line #2 - convert all the .tif files into .png files using ImageMagick
Line #3 - rename all the .tif.png files that were created from Line #2 to .png
Line #4 - remove all the .tif files

Okay? OK, so now we have all of our files as PNG files; we clean up and rebuild:


$ cd ..
$ scons -c
$ scons
$ cd release

Back in the release folder, we run the game again:


$ java -jar LofiWanderings.jar
Tue Mar 03 13:28:02 CST 2009 INFO:Slick Build #213
Tue Mar 03 13:28:02 CST 2009 INFO:LWJGL Version: 1.1
Tue Mar 03 13:28:02 CST 2009 INFO:OriginalDisplayMode: 1440 x 900 x 24 @50Hz
Tue Mar 03 13:28:02 CST 2009 INFO:TargetDisplayMode: 300 x 400 x 0 @0Hz
Tue Mar 03 13:28:02 CST 2009 INFO:Starting display 300x400
Tue Mar 03 13:28:03 CST 2009 INFO:Controllers not available

HURRAY! I did it! ;D

Hope that all this helps someone!

Helps me out, anyway =)

I can't believe I had everything down except for putting the native libs in the right directory.  I knew it was going to turn out to be something simple =)

Also, the png / tiff thing is amusing.  I guess I was being careless when I wrote the tool that generated them.  Slick apparently reads Tiffs just fine on the Mac so I didn't clue in that anything was wrong.

Also, thanks for the info on how to use Scons to build the java project - I'll definitely make use of that in future.

Thanks a bunch for giving me a hand with this - I was really banging my head against the wall before.

Richard Marks:
You are most welcome! 8)
I was happy to help, and I learned a lot of neat things in the process!
I thought it was really cool how your engine works too.
Would you have any issues with me writing a C++ port ?

Quote from: Richard Marks on March 03, 2009, 08:40:51 PM

I thought it was really cool how your engine works too.
Would you have any issues with me writing a C++ port ?

By all means, fill your boots.  There are a few things I would have done differently if I'd been rushing less / will do differently as I work on it in future.  You're welcome to do with it what you like.

Richard Marks:
Cool  8)
I'll be sure to show you the port.


[0] Message Index