Java扫描程序问题(JFrame)

我正在尝试使用扫描仪编辑塔防游戏的等级。 但是它不会将级别(平铺图像)更新为自定义文件的级别(0是草1是石头-1是什么,等等)。 我找到了错误,但我如何解决它,我需要添加/更改什么来摆脱这个?

java.lang.NullPointerException at Levels.loadLevels(Levels.java:11) at Window.define(Window.java:28) at Window.paintComponent(Window.java:44) 

第11行: for(int y=0;y<Window.room.block.length;y++) {第28行: levels.loadLevels(new File("levels/level1.level")); 第44行: define();

这是扫描仪文件:

 import java.io.*; import java.util.*; public class Levels { public void loadLevels(File loadPath) { try { Scanner loadLevelsScanner = new Scanner(loadPath); while(loadLevelsScanner.hasNext()) { for(int y=0;y<Window.room.block.length;y++) { for(int x=0;x<Window.room.block[0].length;x++) { Window.room.block[y][x].groundID = loadLevelsScanner.nextInt(); } } for(int y=0;y<Window.room.block.length;y++) { for(int x=0;x<Window.room.block[0].length;x++) { Window.room.block[y][x].airID = loadLevelsScanner.nextInt(); } } } loadLevelsScanner.close(); } catch(Exception e) { } } } 

这是窗口文件:

 import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.io.*; public class Window extends JPanel implements Runnable { public Thread thread = new Thread(this); public static Image[] tileset_ground = new Image[100]; public static Image[] tileset_air = new Image[100]; public static int myWidth, myHeight; public static boolean isFirst = true; public static Room room; public static Levels levels; public Window() { thread.start(); } public void define() { room = new Room(); levels = new Levels(); levels.loadLevels(new File("levels/level1.level")); for(int i=0;i<tileset_ground.length; i++) { tileset_ground[i] = new ImageIcon("resources/tileset_ground.png").getImage(); tileset_ground[i] = createImage(new FilteredImageSource(tileset_ground[i].getSource(), new CropImageFilter(0, 32 * i, 32, 32))); } for(int i=0;i<tileset_air.length; i++) { tileset_air[i] = new ImageIcon("resources/tileset_air.png").getImage(); tileset_air[i] = createImage(new FilteredImageSource(tileset_air[i].getSource(), new CropImageFilter(0, 32 * i, 32, 32))); } } public void paintComponent(Graphics g) { if(isFirst) { define(); isFirst = false; } g.clearRect(0, 0, getWidth(), getHeight()); room.draw(g); } public void run() { while(true) { if(!isFirst) { room.physic(); } repaint(); try { Thread.sleep(1); } catch(Exception e) { } } } } 

这是房间档案:

 import java.awt.*; public class Room { public int worldWidth = 40; public int worldHeight = 20; public int blockSize = 32; public Block[][] block; public Room () { } public void define () { } public void physic () { } public void draw(Graphics g) { block = new Block[worldHeight][worldWidth]; for(int y=0;y<block.length;y++) { for(int x=0;x<block[0].length;x++) { block[y][x] = new Block(x * blockSize, y * blockSize, blockSize, blockSize, Value.groundGrass, Value.airAir); block[y][x].draw(g); } } } } 

这是块文件:

 import java.awt.*; public class Block extends Rectangle { public int groundID; public int airID; public Block(int x, int y, int width, int height, int groundID, int airID) { setBounds(x, y, width, height); this.groundID = groundID; this.airID = airID; } public void draw(Graphics g) { g.drawImage(Window.tileset_ground[groundID], x, y, width, height, null); if(airID != Value.airAir) { g.drawImage(Window.tileset_air[airID], x, y, width, height, null); } } } 

最后这是扫描仪应该读取的自定义文件:

 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 

抱歉这个愚蠢的问题,我是初学者。

一个快速而肮脏的解决方案是,测试Window.room不为null,以及.block:

  Scanner loadLevelsScanner = new Scanner (loadPath); if ((Window.room != null) && (Window.room.block != null)) { // ... block until catch block } 

一个简单的Testapp我写的作品到目前为止,如果这样做的话。

但是你需要了解“静态”是什么,以及为什么以及如何使用它。 一个常见的初学者错误是,为了使编译器保持沉默而使用“静态”关键字。

调查,按顺序初始化您的类及其属性。

在Block中,要访问Window,您必须有一个引用。 该引用可以传递给Block的ctor:

 class Block extends Rectangle { public int groundID; public int airID; Window window; public Block (int x, int y, int width, int height, int groundID, int airID, Window window) { setBounds (x, y, width, height); this.groundID = groundID; this.airID = airID; this.window = window; } public void draw (Graphics g) { g.drawImage (window.tileset_ground [groundID], x, y, width, height, null); if (airID != Value.airAir) { g.drawImage (window.tileset_air [airID], x, y, width, height, null); } } } 

谁创造了块? 这是房间,所以房间本身需要了解窗户(只要你不从根本上改变你的设计)。

 public Room (Window w) { block = new Block [worldHeight] [worldWidth]; for (int y=0; y  

创建,初始化块数组,并将块传递给Window参数。

在绘制中,您不会一遍又一遍地重新创建数组,也不会重新创建块,而只是重绘它们:

 public void draw (Graphics g) { for (int y=0; y  

在Window中,您创建Room,并将其传递给window-reference:

 public void define () { room = new Room (this); levels = new Levels ();