Java游戏应用程序在Eclipse中工作,但不是作为.jar(Slick2D + LWJGL)

时间:2013-09-01 05:00:30

标签: jar resources lwjgl slick2d

今天我打算把我的游戏装进一个罐子里,提供给一个编码的朋友,并希望看到一个我设法创造的好故障。当我去创建一个Runnable jar时,它会在命令提示符中加载但是为Sounds(.ogg's)抛出Resource Not Found错误,这很好,因为它们不会在它设置的Debug模式下使用。然后它在initTileMap()第137行的TileHanlder.class中抛出了NullPointerException。

我很茫然所以我来到StackOverflow,因为我花了将近一整天的时间来获得一个工作的Jar。我也试过JarSplice。

我的主要问题是,如果您注意到任何异常或我没做过的事情导致资源无法在.jar中找到。

所有代码和资源都在同一个罐子里,一个罐子里没有多个罐子

对于我的所有代码(毕竟它是OpenSource:Game Source Code

Level.java(调用AssetHandler和TileHandler的类)

public class Level extends BasicGameState {

public MapHandler map = new MapHandler();
public AssetHandler asset = new AssetHandler();
static OutputHandler out = new OutputHandler();

public GameContainer container;
public StateBasedGame game;

public static float MouseX = 0;
public static float MouseY = 0;
public float RectX = 0;
public float RectY = 0;
public int tileAmount = 0;
public static int mapID = 1;
public static int delta;
public static int score = 0;
private static int EntityAmount = 0;
private static int ActiveEntityAmount = 0;

private int FPS = 0;

public static Image mapImage;
public static TileHandler Tile = new TileHandler();
public Point mousePoint;
public Circle mouseCirc;

public static Player p;
public static Enemy Blinky, Pinky, Inky, Clyde;
public static EntityAI AGGRESSIVE, AMBUSH, HIT_RUN, SORTOFRANDOM;

public Level(int id) {

}

@Override
public void init(GameContainer container, StateBasedGame game) throws SlickException {

    MapHandler.mapRect();
    mapID = MapHandler.getMapID();
    MapHandler.deployMap(mapID);

    try {
        asset.initAssets();
        OutputHandler.initFont();
    } catch (AssetException e) {
        e.printStackTrace();
    }

    TileHandler.initTileMap();
    container.setUpdateOnlyWhenVisible(true);
    container.setShowFPS(false);
    container.setSmoothDeltas(false);
    container.setVerbose(true);

    this.container = container;
    this.game = game;

    AGGRESSIVE = new RedAI();
    AMBUSH = new PinkAI();
    HIT_RUN = new BlueAI();
    SORTOFRANDOM = new OrangeAI();

    p = new Player("Player1");
    Blinky = new Enemy("Shadow", AGGRESSIVE);
    Pinky = new Enemy("Speedy", AMBUSH);
    Inky = new Enemy("Bashful", HIT_RUN);
    Clyde = new Enemy("Pokey", SORTOFRANDOM);
}

@Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {

    Tile.drawTileMap(TileHandler.tileLayer, TileHandler.tMapTiles, g);
    if (Reference.debug) {
        displayTileBounds(TileHandler.tileLayer, g);
    }
    drawEntities();
    drawStrings(g);
}

@Override
public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
    Input in = container.getInput();

    MouseX = in.getMouseX();
    MouseY = in.getMouseY();
    RectX = MapHandler.Map32.getX();
    RectY = MapHandler.Map32.getY();
    EntityAmount = Entity.entityList.size();
    ActiveEntityAmount = Enemy.enemyList.size() + Projectile.activeProjectiles.size() + 1;
    Level.delta = delta;
    Reference.defProjectileVelocity = .13f * Level.delta;

    p.update(in);
    updateNonPlayerEntities();

    FPS = container.getFPS();
}

@Override
public int getID() {

    return 2;
}

/** @deprecated **/
@Deprecated
protected void drawMap(Graphics g) {

    g.drawImage(mapImage, Reference.MAP_X, Reference.MAP_Y);

}

protected void drawStrings(Graphics g) {

    if (Reference.debug) {
        OutputHandler.write("FPS: " + Integer.toString(FPS), 11, 10);
        OutputHandler.write(String.format("Mouse X: %s, Mouse Y: %s", MouseX, MouseY), 11, 30);
        OutputHandler.write(String.format("Rect X: %s, Y: %s", RectX, RectY), 11, 50);
        OutputHandler.write("Amount of Tiles: " + (TileHandler.tileLayer.length * TileHandler.tileLayer[0].length), 11, 70);
        OutputHandler.write(String.format("Amount of Entities = %s", Integer.toString(EntityAmount)), 11, 90);
        OutputHandler.write(String.format("Active Entities = %s", Integer.toString(ActiveEntityAmount)), 11, 110);
        out.write("Currently Loaded: " + p.isReloaded(), 11, 130);

        OutputHandler.write("Amount of Entities is Accumulative", 11, 666);
    } else {
        String curTime = Reference.getTime();
        String scoreStr = Reference.convertScore(score);
        OutputHandler.write("Time: " + curTime, 11, 10);
        OutputHandler.write("Score: " + scoreStr, 550, 10);
    }
}

protected void displayTileBounds(Rectangle[][] tileLayer, Graphics g) {
    g.setColor(Color.white);
    for (int x = 0; x < tileLayer.length; x++) {
        for (int y = 0; y < tileLayer[0].length; y++) {
            g.fill(tileLayer[x][y]);
        }
    }
    g.setColor(Color.magenta);

    for (int s = 0; s < TileHandler.collisionTiles.size(); s++) {
        Rectangle r = TileHandler.collisionTiles.get(s);
        g.fill(r);
    }
    g.setColor(Color.orange);
    g.fill(p.boundingBox);

    for (int z = 0; z < Entity.teleportingTiles.length; z++) {
        Rectangle r = Entity.teleportingTiles[z];
        g.fill(r);
    }
}

protected void drawEntities() {
    ArrayList<Entity> list = Entity.entityList;

    for (int i = 0; i < list.size(); i++) {

        list.get(i).drawEntity(list.get(i));

    }
}

protected void updateNonPlayerEntities() {
    ArrayList<Enemy> list = Enemy.enemyList;

    for (int i = 0; i < list.size(); i++) {
        list.get(i).update();
    }

    ArrayList<Projectile> pList = Projectile.activeProjectiles;

    for (int p = 0; p < pList.size(); p++) {
        pList.get(p).update();
    }
}

}

AssetHandler(Game-Handlers-AssetHandler.java)声音是第三种方法

public class AssetHandler {

public static boolean isComplete = false;

private static String musPath = "res/Sounds/";
static TileHandler tile;

private static int tsize = 32;

private static String spritesPath = "res/GameSprites/Maze Game/sprites.png";
private static String terrainPath = "res/GameSprites/Maze Game/terrain.png";
private static String twPath = "res/GameSprites/Maze Game/animation/tankToWest.png";
private static String tePath = "res/GameSprites/Maze Game/animation/tankToEast.png";
private static String tnPath = "res/GameSprites/Maze Game/animation/tankToNorth.png";
private static String tsPath = "res/GameSprites/Maze Game/animation/tankToSouth.png";
private static String bwPath = "res/GameSprites/Maze Game/animation/blueToWest.png";
private static String bePath = "res/GameSprites/Maze Game/animation/blueToEast.png";
private static String bnPath = "res/GameSprites/Maze Game/animation/blueToNorth.png";
private static String bsPath = "res/GameSprites/Maze Game/animation/blueToSouth.png";

private static String rePath, rwPath, rsPath, rnPath;
private static String pePath, pwPath, psPath, pnPath;
private static String oePath, owPath, osPath, onPath;



public static Music titleMus1, titleMus2, titleMus3, loadingScreenMus1, loadingScreenMus2, loadingScreenMus3;

public static Sound tankMove, tankFire, tankExplode, tankSurrender, tankRetreat;




public static void initSounds() {

    System.out.println("Initializing Main Menu Music...");
    try {
        titleMus1 = new Music(musPath + "title/titlefirst.ogg");
        titleMus2 = new Music(musPath + "title/titlesecond.ogg");
        titleMus3 = new Music(musPath + "title/titlethird.ogg");

        System.out.println("Initialized Main Menu Music!...");
    } catch (SlickException e) {
        e.printStackTrace();
        System.out.println("ERROR: Initializing Main Menu Sounds at " + "com.treehouseelite.tank.game.handlers.AssetHandler" + " : initSounds() Method, First Try/Catch");
    }
    System.out.println("Initializing Loading Screen Music...");
    try {
        loadingScreenMus1 = new Music(musPath + "levels or loading screens/ActionBuilder.ogg");
        loadingScreenMus2 = new Music(musPath + "levels or loading screens/StruggleforSurvival.ogg");
        loadingScreenMus3 = new Music(musPath + "levels or loading screens/SurrealSomber.ogg");
    } catch (SlickException e) {
        e.printStackTrace();
        System.out.println("ERROR: Initializing Loading Screen Sounds at " + "com.treehouseelite.tank.game.handlers.AssetHandler" + " : initSounds() Method, Second Try/Catch");
    }
    initSFX();
    initsComplete();
}

private static void initsComplete() {
    System.out.println("========================ALL ASSETS INITIALIZED========================");
}

public static void initSFX() {

    try {
        tankMove = new Sound("res/Sounds/SFX/tankMove.wav");
    } catch (SlickException e) {
        e.printStackTrace();
    } finally {
        System.out.println("All Sound Effects Initialized...");
    }
}

}

TileHandler.java(Game-Handlers-TileHandler.java)

public class TileHandler {

public static String mapPath = "res/World/level_";

public static int bg, paths, collision;

public static Image[][] tMapTiles = new Image[25][20];

public static boolean[][] collidableTile = new boolean[25][20];

static Graphics g = new Graphics();
static AssetHandler asset = new AssetHandler();

// The Amount of Image is too damn high!

static TiledMap tMap;

public static int wFrame = 0;

private static int id;

public static Rectangle[][] tileLayer = new Rectangle[25][20];
public static ArrayList<Rectangle> collisionTiles = new ArrayList<Rectangle>(500);

public TileHandler() {

}

public TileHandler(int id, Rectangle rect) {

    TileHandler.id = id;

    try {
        createTiles(id, rect);
    } catch (SlickException e) {
        e.printStackTrace();
    }
}

protected void createTiles(int id, Rectangle layer) throws SlickException {
    // Scans 0,0 to 0,20 of the tiles and then moves down the x line
    // gettings tiles
    // 0,0 = tileLayer[0][0]
    mapPath = String.format("res/World/level_%s.tmx", id);

    tMap = new TiledMap(mapPath);

    bg = tMap.getLayerIndex("background");
    paths = tMap.getLayerIndex("paths");
    collision = tMap.getLayerIndex("collision");
    // Constructs a Grid of Rectangles based on the Map's Top Left point

    for (int i = 0; i < tileLayer.length; i++) {
        for (int y = 0; y < tileLayer[0].length; y++) {
            Rectangle tile = new Rectangle((i + Reference.MAP_X) + (i * Reference.TILE_SIZE), (y + Reference.MAP_Y) + (y * Reference.TILE_SIZE), 32, 32);
            tileLayer[i][y] = tile;
        }
    }
    /*
     * for(int x = 0; x<collisionTiles.length; x++){ for(int y = 0;
     * y<collisionTiles[0].length; y++){ Rectangle tile = new
     * Rectangle((x+Reference.MAP_X) + (x*31),
     * (y+Reference.MAP_Y+14)+(y*31),32,32); collisionTiles[x][y] = tile; }
     * }
     */

}

/** @deprecated */
@Deprecated
public static void initSprites(Rectangle[][] layer) {

    bg = tMap.getLayerIndex("background");
    paths = tMap.getLayerIndex("paths");
    collision = tMap.getLayerIndex("collision");

    System.out.println("Initialized Sprites!");

}

// Initializes all tiles and put them into Image and Boolean Arrays
// Boolean Array for later use with determining whether the player or entity
// can be there. (collidableTile)
// Image array holds the tiles (tMapTiles)
public static void initTileMap() {
    new Graphics();


    // Getting Tiles based off Tile ID's
    /** DIRT PATH MAPS (Dev Map, Level 1) **/
    if ((id == 0) || (id == 1)) {
        for (int x = 0; x < tileLayer.length; x++) {
            for (int y = 0; y < tileLayer[0].length; y++) {
                Rectangle r = new Rectangle(tileLayer[x][y].getX(), tileLayer[x][y].getY(), 32, 32);

                if (tMap.getTileId(x, y, bg) == 1) {
                    tMapTiles[x][y] = AssetHandler.sparseGrass;

                }

                if (tMap.getTileId(x, y, collision) == 2) {
                    tMapTiles[x][y] = AssetHandler.water11;

                    collisionTiles.add(r);

                }
                if (tMap.getTileId(x, y, collision) == 57) {
                    tMapTiles[x][y] = AssetHandler.concrete1;

                    collisionTiles.add(r);

                }
                if (tMap.getTileId(x, y, collision) == 71) {
                    tMapTiles[x][y] = AssetHandler.concrete2;

                    // collisionTiles.add(new
                    // Rectangle(tileLayer[x][y].getX(),
                    // tileLayer[x][y].getY()+14, 32, 32)) ;
                    collisionTiles.add(r);
                }
                if (tMap.getTileId(x, y, collision) == 85) {
                    tMapTiles[x][y] = AssetHandler.concrete3;

                    collisionTiles.add(r);

                }
                if (tMap.getTileId(x, y, collision) == 72) {
                    tMapTiles[x][y] = AssetHandler.metal1;

                    collisionTiles.add(r);

                }
                if (tMap.getTileId(x, y, collision) == 58) {
                    tMapTiles[x][y] = AssetHandler.metal2;

                    collisionTiles.add(r);

                }
                if (tMap.getTileId(x, y, paths) == 50) {
                    tMapTiles[x][y] = AssetHandler.hDirtPath;

                }
                if (tMap.getTileId(x, y, paths) == 60) {
                    tMapTiles[x][y] = AssetHandler.dirtPath;

                }
                if (tMap.getTileId(x, y, paths) == 59) {
                    tMapTiles[x][y] = AssetHandler.dirtPathTurn4;

                }
                if (tMap.getTileId(x, y, paths) == 73) {
                    tMapTiles[x][y] = AssetHandler.dirtPathTurn3;

                }
                if (tMap.getTileId(x, y, paths) == 79) {
                    tMapTiles[x][y] = AssetHandler.dirtThreewayRight;

                }
                if (tMap.getTileId(x, y, paths) == 46) {
                    tMapTiles[x][y] = AssetHandler.dirtPathTurn1;

                }
                if (tMap.getTileId(x, y, paths) == 37) {
                    tMapTiles[x][y] = AssetHandler.hDirtCrossing1;

                }
                if ((tMap.getTileId(x, y, paths) == 80) || (tMap.getTileId(x, y, paths) == 88)) {
                    tMapTiles[x][y] = AssetHandler.dirtThreewayLeft;

                }
                if (tMap.getTileId(x, y, paths) == 102) {
                    tMapTiles[x][y] = AssetHandler.dirtThreewayDown;

                }
                if (tMap.getTileId(x, y, paths) == 74) {
                    tMapTiles[x][y] = AssetHandler.dirtPathTurn2;

                }
                if (tMap.getTileId(x, y, paths) == 107) {
                    tMapTiles[x][y] = AssetHandler.dirtThreewayUp;

                }
                if (tMap.getTileId(x, y, paths) == 88) {
                    tMapTiles[x][y] = AssetHandler.dirtCrossroads;

                }

            }
        }
    }

}

public void drawTileMap(Rectangle[][] layer, Image[][] tiles, Graphics g) {

    // Loops through the Image array and places tile based on the Top Left
    // corner of the Rectangle in the rectangle array
    // Rectangle Array = layer (tileLayer was passed)
    // Image Array = tiles (tMapTiles was passed)
    // Asset Refers to Asset Handler
    for (int x = 0; x < layer.length; x++) {
        for (int y = 0; y < layer[0].length; y++) {
            g.drawImage(tiles[x][y], layer[x][y].getX(), layer[x][y].getY());

            // Below here is image detection for the placement of Animations
            if (tiles[x][y] == AssetHandler.water11) {
                AssetHandler.vRiver1.draw(layer[x][y].getX(), layer[x][y].getY());
                AssetHandler.vRiver1.start();
                AssetHandler.vRiver1.update(Level.delta);
            } else if (tiles[x][y] == AssetHandler.hDirtCrossing1) {
                AssetHandler.hDirtCrossing.draw(layer[x][y].getX(), layer[x][y].getY());
                AssetHandler.hDirtCrossing.start();
                AssetHandler.hDirtCrossing.update(Level.delta);
            }
        }
    }
}

}

最后,MapHandler.java - 非常稀疏使用,主要目标是初始化TileHandler对象以构造用于构造TiledMap的tile网格。

public class MapHandler {

public static AssetHandler asset = new AssetHandler();

static Image devMap;

Image map_1;

Image map_2;

Image map_3;

public static Rectangle Map32;

public MapHandler() {
}

// Sends a Rectangle set Around the Map Image to TileHandler
// to construct a grid of 32x32 Rectangles inside the Map's Rectangle
public static void deployMap(int id) {
    if (id == 0) {
        new TileHandler(id, Map32);
    }
}

// Randomly Generates a Map ID corresponding to a Level_X.tmx
// Currently set to 0 for development purposes
public static int getMapID() {
    new Random();
    return 0;
    // return id;
}

/* Create the Rectangle and Grid */
public static void mapRect() throws SlickException {

    System.out.println("Initializing Rectangular Plane...");
    Map32 = new Rectangle(Reference.GUI_WIDTH / 24, Reference.GUI_HEIGHT / 24, 800, 640);
    System.out.println("Map32 Initialized!...");
}

}

如果您需要任何其他资源或信息,请告诉我,我很乐意提供,所以我可以克服这个问题。我也会考虑其他方式,谢谢你的回复!

由于问题文本框中的30k字符限制,有什么东西被删除了。主要是在疯狂拥挤的AssetHandler.java中,它仍然存在于git存储库中。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。经过一段时间的搜索,我遇到了这个简洁的解决方案。请参阅this LWJGL forum post

    public static void main(String[] args) throws SlickException {
        /* Set lwjgl library path so that LWJGL finds the natives depending on the OS. */
        String osName = System.getProperty("os.name");
        // Get .jar dir. new File(".") and property "user.dir" will not work if .jar is called from
        // a different directory, e.g. java -jar /someOtherDirectory/myApp.jar
        String nativeDir = "";
        try {
            nativeDir = new File(GameMain.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent();
        } catch (URISyntaxException uriEx) {
            try {
                // Try to resort to current dir. May still fail later due to bad start dir.
                uriEx.printStackTrace();
                nativeDir = new File(".").getCanonicalPath();
            } catch (IOException ioEx) {
                // Completely failed
                ioEx.printStackTrace();
                JOptionPane.showMessageDialog(new JFrame(), "Failed to locate native library directory. " +
                        "Error:\n" + ioEx.toString(), "Error", JOptionPane.ERROR_MESSAGE);
                System.exit(-1);
            }
        }
        // Append library subdir
        nativeDir += File.separator + "lib" + File.separator + "native" + File.separator;
        if (osName.startsWith("Windows")) {
            nativeDir += "windows";
        } else if (osName.startsWith("Linux") || osName.startsWith("FreeBSD")) {
            nativeDir += "linux";
        } else if (osName.startsWith("Mac OS X")) {
            nativeDir += "macosx";
        } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
            nativeDir += "solaris";
        } else {
            JOptionPane.showMessageDialog(new JFrame(), "Unsupported OS: " + osName + ". Exiting.",
                    "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(-1);
        }
        System.setProperty("org.lwjgl.librarypath", nativeDir);
    }

请记住,您需要在同一目录中使用lib文件夹。我把我的存储在.jar之外,但也可以将它放在里面。还要注意,它需要在你做任何LWJGL之前发生,所以主要的方法是个好地方。