LWJGL game works fine in eclipse, but doesn't when exported

Hi!
I made a small puzzle with textures. I used lwjgl.jar, lwjgl_util.jar and slick-util.jar. It works fine in eclipse but not when exported.

Main.java
[spoiler]


package example;

public class Main {
	public static void main(String[] args) {
		new LWJGLInput();
	}
}


[/spoiler]

LWJGLInput.java
[spoiler]


package example;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glOrtho;
import static org.lwjgl.opengl.GL11.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;


public class LWJGLInput {
	
	List<Box> boxes = new ArrayList<Box>(16);
	boolean select = false;
	
	
	public Texture loadTexture(String key){
		try {
			return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/" + key + ".png")));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	public LWJGLInput(){
		try {
			Display.setDisplayMode(new DisplayMode(640, 480));
			Display.setTitle("Puzzle");
			Display.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
		}
		//65
		boxes.add(new Box(15, 15));
		boxes.add(new Box(200, 150));
		boxes.add(new Box(15, 115));
		
		
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, 640, 480, 0, 1, -1);
		glMatrixMode(GL_MODELVIEW);
		glEnable(GL_TEXTURE_2D);
		
		
		while (!Display.isCloseRequested()){
			glClear(GL_COLOR_BUFFER_BIT);
			
			
			
			if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
				Display.destroy();
				System.exit(0);
			}
			
			for(Box box : boxes){
				if(Mouse.isButtonDown(0) && box.isInBounds(Mouse.getX(), 480 - Mouse.getY()) && !select && (boxes.indexOf(box)==1)){ 
					box.selected = true;
					select = true;
				}
				
				if(Mouse.isButtonDown(1)){
					box.selected = false;
					select = false;
				}
				
				if (box.selected){
					box.update(Mouse.getDX(), -Mouse.getDY());
				}
				
				if(boxes.indexOf(box) == 1 && (box.x == 15) && (box.y == 65)){

					
					if(!box.selected){
						while(true){
						System.out.println("You win the game!");
						System.out.println("Thanks for playing! :)");
						System.exit(0);
						
					}
					}
				}
				
				box.draw();
				
			}
		
			
			
			Display.update();
			Display.sync(60);
		}
		
		Display.destroy();
		
		
		}
	

	
}
	

[/spoiler]

Box.java
[spoiler]


package example;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glVertex2f;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Random;

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

public class Box {
		Texture wood;
		int x,y;
		float cRed, cBlue, cGreen;
		public boolean selected = false;
		
		Box(int x, int y){
			this.x = x;
			this.y = y;
			
			Random ran = new Random();
			
			cRed = ran.nextFloat();
			cBlue = ran.nextFloat();
			cGreen = ran.nextFloat();
		}
		
		void randomize(){
			Random ran = new Random();
			cRed = ran.nextFloat();
			cBlue = ran.nextFloat();
			cGreen = ran.nextFloat();
		}
		
		void draw(){
			wood = loadTexture("wood");
			wood.bind();
			
			
			int a = x;
			int b = y;
			int c = x+50;
			int d = y + 50;
			
			glBegin(GL_QUADS);
				glTexCoord2f(0,0);
				glVertex2f(a, b);
				glTexCoord2f(1,0);
				glVertex2f(c, b);
				glTexCoord2f(1,1);
				glVertex2f(c, d);
				glTexCoord2f(0,1);
				glVertex2f(a, d);
			glEnd();
			
		}
		
		void update(int dx, int dy){
			x += dx;
			y += dy;
		}
		
		boolean isInBounds(int mouseX, int mouseY) {
            return mouseX > x && mouseX < x + 50 && mouseY > y && mouseY < y + 50;
        }
		
		public Texture loadTexture(String key){
			try {
				return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/" + key + ".png")));
			} catch (FileNotFoundException e) {
				
			} catch (IOException e) {
				
			}
			return null;
		}
	

}

[/spoiler]

I used jarsplice to compile it all. In case you want to inspect the jar file through winrar, here it is:-
https://www.mediafire.com/?oba961abs7sysw3

So here is the problem. I try to run it (double click it), it comes for a second and disappears. This doesn’t happen in eclipse.

I tried running it through the command prompt and I got an exception - NullPointer.

[spoiler]

Exception in thread "main" java.lang.NullPointerException
        at example.Box.draw(Box.java:44)
        at example.LWJGLInput.<init>(LWJGLInput.java:104)
        at example.Main.main(Main.java:5)

[/spoiler]

If it isn’t null in eclipse, why does the variable become null when exported?

Please help me.

Regards,
Ablaze.

Never swallow exceptions.


public Texture loadTexture(String key){
    try {
        return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/" + key + ".png")));
    } catch (Exception e) {
+       e.printStackTrace();
    }
    return null;
}

Okay, so here is the new stack trace:-
[spoiler]


java.io.FileNotFoundException: res\wood.png (The system cannot find the path spe
cified)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at example.Box.loadTexture(Box.java:76)
        at example.Box.draw(Box.java:43)
        at example.LWJGLInput.<init>(LWJGLInput.java:104)
        at example.Main.main(Main.java:5)
Exception in thread "main" java.lang.NullPointerException
        at example.Box.draw(Box.java:44)
        at example.LWJGLInput.<init>(LWJGLInput.java:104)
        at example.Main.main(Main.java:5)

[/spoiler]

So the file isn’t found. Where exactly am I supposed to place my res folder?

res stands for resources.

Regards,
Ablaze.

I have the same problem that’s why I didn’t publish Craftia.

Try changing this line


return TextureLoader.getTexture("PNG", new FileInputStream(new File("res/" + key + ".png")));

To


return TextureLoader.getTexture("PNG", this.getClass().getClassLoader().getResourceAsStream("res/" + key + ".png"));

Bundle your resources in a jar file, put that on the class path along with the other jars you use, then use the resource API to get at them rather than loading directly from the file system. They don’t actually have to be in a jar, but it simplifies distribution. Search these forums for getResourceAsStream and you should find a number of posts about it. Or look to Google, where you can also find advice on how to set things up in Eclipse so that this approach works the same way in the IDE and out.

With your current approach, you’re trying to load relative to the current working directory. In the IDE, that’s easy. Outside, it can be literally anything. Going through the resourceAPI can mask all that.

Hmm… I didn’t exactly understand what you said. I just started LWJGL programming day before yesterday, so I don’t know much. What is resourceAPI? Can you link me to a tutorial about it? And by class path, what do you mean? I know the system variable PATH, but I don’t know what class path is.

Did this, and now it doesn’t work even in eclipse.

Regards,
Ablaze.

Can you post a screenshot of your eclipse package explorer?

This has nothing to do with LWJGL. It’s about loading resources in Java.

[quote]What is resourceAPI?
[/quote]
I’m talking about the getResourceAsStream method and it’s companion getResource.

Ask Google. This is basic Java stuff here, so there should be a plethora of information about it out there. I don’t know what’s good and what’s not, though, these days.

This is where the JVM looks to find the Java classes needed to run your program. Again, basic Java knowledge that a good java tutorial or book can tell you about. Ask Google.

You need to configure things properly for it to work in eclipse.

I strongly suggest you go out and read up on class paths and how to load Java resources, else all the advice you get here is just going to keep leading to issues you don’t know how to solve. A couple of good tutorials should help you figure it all out.

I’m talking about the getResourceAsStream method and it’s companion getResource.

Ask Google. This is basic Java stuff here, so there should be a plethora of information about it out there. I don’t know what’s good and what’s not, though, these days.

This is where the JVM looks to find the Java classes needed to run your program. Again, basic Java knowledge that a good java tutorial or book can tell you about. Ask Google.

You need to configure things properly for it to work in eclipse.

I strongly suggest you go out and read up on class paths and how to load Java resources, else all the advice you get here is just going to keep leading to issues you don’t know how to solve. A couple of good tutorials should help you figure it all out.
[/quote]
Okay I’ll look at it.

Here:-

I’ve blackened out some personal info.

Regards,
Ablaze.

Just drag the ‘res’ folder into ‘src’ and it should work.

Thanks, it works!

Can you explain why it wasn’t working with the other one?

P.S. I also have another problem, please have a look at it here - http://www.java-gaming.org/topics/after-using-slick-for-textures-game-lags-too-much/31438/view.html.

Regards,
Ablaze.

It wasn’t working because you can’t use File inside JAR files. You have to use getResourceAsStream(String) from a Class object, which you can obtain by calling getClass().getResourceAsStream(String) on any object or by doing MyClassName.class.getResourceAsStream(String) where “MyClassName” is the root class for relative paths.

In your code, you did new File(“res/” + key + “.png”), which without a leading forward slash is a relative path, relative to the current directory: the project root folder. With your “res” folder there, it worked fine. When you used SHC’s code for this.getClass().getClassLoader().getResourceAsStream(String), it was looking relative to the package root, which is the “src” folder. Moving the “res” into “src” fixed that.

Recap:

[tr]
	[td][/td][td]Relative[/td][td]Absolute (relative to root)[/td]
[/tr]
[tr]
	[td]File (resource NOT in JAR)[/td]
	[td]new File("relative/path/")[/td]
	[td]new File("/relative/to/file/system/root/")[/td]
[/tr]
[tr]
	[td]getResource(String)

(Resource in JAR or file system)[/td]
[td]getClass().
getResource(“relative/to/Class”)[/td]
[td]getClass().getClassLoader().
getResource(“relative/to/package/root”)[/td]
[/tr]
[tr]
[td]getResourceAsStream(string)
(Resource in JAR or file system)[/td]
[td]getClass().
getResourceAsStream(“relative/to/Class”)[/td]
[td]getClass().getClassLoader().
getResourceAsStream(“relative/to/package/root”)[/td]
[/tr]

As you are using slick-util, another easier option available to you is to use its ResourceLoader and let it worry about whether the resource is in a jar or on the filesystem.

Simply use ResourceLoader.getResourceAsStream(), if you want an InputStream or ResourceLoader.getResource() if you want an URL.

Javadoc here.