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

Java游戏应用程序在Eclipse中工作,但不是作为.jar(Slick2D+;LWJGL),jar,resources,lwjgl,slick2d,Jar,Resources,Lwjgl,Slick2d,今天,我打算把我的游戏打包到一个罐子里,提供给一个朋友,他编写了代码,希望看到我成功创建的一个很好的小故障。当我把它变成一个可运行的jar时,它会在命令提示符中加载,但会抛出Resource Not Found errors for Sounds(.ogg),这很好,因为它们不会在设置为的调试模式中使用。然后它在initTileMap()行的TileHanlder.class中抛出了一个NullPointerException 我不知所措,所以我来到StackOverflow,因为我几乎花了一整

今天,我打算把我的游戏打包到一个罐子里,提供给一个朋友,他编写了代码,希望看到我成功创建的一个很好的小故障。当我把它变成一个可运行的jar时,它会在命令提示符中加载,但会抛出Resource Not Found errors for Sounds(.ogg),这很好,因为它们不会在设置为的调试模式中使用。然后它在initTileMap()行的TileHanlder.class中抛出了一个NullPointerException

我不知所措,所以我来到StackOverflow,因为我几乎花了一整天的时间来买一个工作罐。我也试过了

我的主要问题是,您是否注意到了任何异常,或者我没有做的事情导致在.jar中找不到资源

所有代码和资源都在同一个JAR中,一个JAR代表所有内容,而不是多个JAR

对于我所有的代码(毕竟它是开源的:)

java(调用AssetHandler和TileHandler的类)

java(游戏处理程序TileHandler.java)

如果您需要任何其他资源或信息,请让我知道,我将很乐意提供,以便我可以克服这一点。我也会想其他的办法,谢谢大家的回复


由于问题文本框上的字符数限制为30k,因此内容被删除。主要是在极其拥挤的AssetHandler.java中,它仍然存在于git存储库中。

我也遇到了同样的问题。在寻找了一段时间后,我发现了这个简洁的解决方案。看

请记住,在同一目录中需要一个lib文件夹。我把我的放在了.jar的外面,但也可以放在里面。还要注意的是,它需要在执行任何LWJGL操作之前发生,因此主方法是一个好地方

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();
    }
}

}
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...");
    }
}

}
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);
            }
        }
    }
}

}
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!...");
}

}
    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);
    }