Java 2D Tile地图加载异常:未读取txt配置仅显示单一Tile
Java 2D游戏地图读取异常排查与修复
问题现状
跟随Java 2D游戏教程开发时,可单独显示单个Tile,但读取map01.txt配置生成地图时,仅渲染单一Tile,与预期地图样式不符。
相关文件内容
map01.txt内容
1001111111111111 1000000000000001 1000000000000001 1000000000000001 1000000000000001 1000000000000001 1000000000000001 1000002222000001 1000002222000001 1000002222000001 1000002222000001 1111111111111111
Tile.java
package tile; import java.awt.image.BufferedImage; public class Tile { public BufferedImage image; public boolean collision = false; }
TileManager.java
package tile; import java.awt.Graphics2D; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.imageio.ImageIO; import main.GamePanel; public class TileManager { GamePanel gp; Tile[] tile; int mapTileNum[][]; public TileManager(GamePanel gp) { this.gp = gp; tile = new Tile[10]; mapTileNum = new int[gp.maxScreenCol][gp.maxScreenRow]; getTileImage(); loadMap(); } public void getTileImage() { try { tile[0] = new Tile(); tile[0].image = ImageIO.read(getClass ().getResourceAsStream("/tiles/Grass.png")); tile[1] = new Tile(); tile[1].image = ImageIO.read(getClass ().getResourceAsStream("/tiles/Wall.png")); tile[2] = new Tile(); tile[2].image = ImageIO.read(getClass ().getResourceAsStream("/tiles/Water.png")); }catch(IOException e) { e.printStackTrace(); } } public void loadMap() { try { InputStream is = getClass().getResourceAsStream("/maps/map01.txt"); BufferedReader br = new BufferedReader( new InputStreamReader(is)); int col = 0; int row = 0; while(col < gp.maxScreenCol && row < gp.maxScreenRow) { String line = br.readLine(); while(col < gp.maxScreenCol) { String numbers[] = line.split(" "); int num = Integer.parseInt(numbers[col]); mapTileNum[col][row] = num; col++; } if(col == gp.maxScreenCol) { col = 0; row++; } } br.close(); }catch(Exception e) { } } public void draw(Graphics2D g2) { int col = 0; int row = 0; int x = 0; int y = 0; while(col < gp.maxScreenCol && row < gp.maxScreenRow) { int tileNum = mapTileNum[col][row]; g2.drawImage(tile[tileNum].image, x, y, gp.tileSize, gp.tileSize, null); col++; x += gp.tileSize; if(col == gp.maxScreenCol) { col = 0; x = 0; row++; y += gp.tileSize; } } } }
GamePanel.java
package main; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JPanel; import entity.Player; import tile.TileManager; public class GamePanel extends JPanel implements Runnable{ // SCREEN SETTINGS final int originalTileSize = 16; // 16x16 tile final int scale = 3; public final int tileSize = originalTileSize * scale; // 48x48 tile public final int maxScreenCol = 16; public final int maxScreenRow = 12; public final int screenWidth = tileSize * maxScreenCol; // 768 pixels public final int screenHeight = tileSize * maxScreenRow; // 576 pixels // FPS int FPS = 60; TileManager tileM = new TileManager(this); KeyHandler keyH = new KeyHandler(); Thread gameThread; Player player = new Player(this,keyH); public GamePanel() { this.setPreferredSize(new Dimension(screenWidth, screenHeight)); this.setBackground(Color.white); this.setDoubleBuffered(true); this.addKeyListener(keyH); this.setFocusable(true); } public void startGameThread() { gameThread = new Thread(this); gameThread.start(); } @Override public void run() { double drawInterval = 1000000000/FPS; double delta = 0; long lastTime = System.nanoTime(); long currentTime; long timer = 0; int drawCount =0; while(gameThread != null) { currentTime = System.nanoTime(); delta += (currentTime - lastTime) / drawInterval; timer += (currentTime - lastTime); lastTime = currentTime; if(delta >= 1) { update(); repaint(); delta--; drawCount++; } if(timer >= 1000000000) { System.out.println("FPS:" + drawCount); drawCount = 0; timer = 0; } } } public void update() { player.update(); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2= (Graphics2D)g; tileM.draw(g2); player.draw(g2); g2.dispose(); } }
效果对比
- 预期效果:

- 实际效果:

问题原因
- 地图读取逻辑错误:
loadMap()方法中,使用line.split(" ")按空格分割每行内容,但map01.txt的行是连续无空格的数字串,导致分割后仅得到一个元素。当col>0时,numbers[col]会触发数组越界异常。 - 异常静默处理:
catch(Exception e)块未做任何输出,掩盖了数组越界错误,导致程序中断后无法正常读取后续地图数据,最终所有Tile都使用初始值渲染。
修复方案
修改TileManager类中的loadMap()方法,直接读取每行的单个字符并转换为数字,同时添加异常输出便于调试:
public void loadMap() { try { InputStream is = getClass().getResourceAsStream("/maps/map01.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(is)); int row = 0; while(row < gp.maxScreenRow) { String line = br.readLine(); if(line == null) break; int col = 0; while(col < gp.maxScreenCol && col < line.length()) { char tileChar = line.charAt(col); int tileNum = Character.getNumericValue(tileChar); mapTileNum[col][row] = tileNum; col++; } row++; } br.close(); }catch(Exception e) { e.printStackTrace(); } }
额外优化建议
- 不要捕获
Exception后静默处理,打印堆栈信息可快速定位问题。 - 添加文件内容与屏幕行列数的校验,避免因文件行数/列数不足导致的异常。
内容的提问来源于stack exchange,提问作者Alan Morgan
相关产品推荐
相关产品推荐

