You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

效果对比

  • 预期效果:预期效果
  • 实际效果:实际效果

问题原因

  1. 地图读取逻辑错误:loadMap()方法中,使用line.split(" ")按空格分割每行内容,但map01.txt的行是连续无空格的数字串,导致分割后仅得到一个元素。当col>0时,numbers[col]会触发数组越界异常。
  2. 异常静默处理: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:24:51