Java 将地图添加到游戏后出现越界错误

Java error out of bounds after adding a Map to game

我最近几天在做一个小游戏,已经取得了巨大的进步。现在我遇到了一个问题,我看不到需要解决的问题。它说

"Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 
Index 8 out of bounds for length 8 at tileMap.TileMap.draw(TileMap.java:158)
    at gameState.Level1State.draw(Level1State.java:38)
    at gameState.GameStateManager.draw(GameStateManager.java:33)
    at main.GamePanel.draw(GamePanel.java:102)
    at main.GamePanel.run(GamePanel.java:79)
    at java.base/java.lang.Thread.run(Thread.java:832)

我看了一个小时,但什么也没看到。有人可以找到导致错误的错误吗?编辑:我删除了没有错误的代码。

GamePanel:

package main;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

import gameState.GameStateManager;

public class GamePanel extends JPanel implements Runnable, KeyListener{
    
    // Dimensionen
    public static final int WIDTH  = 320;
    public static final int HEIGHT = 240;
    public static final int SCALE  = 2;
        
    
    
    // game thread
    private Thread thread;
    private boolean running;
    private int FPS = 60;
    private long targetTime = 1000 / FPS;
    
    //image
    private BufferedImage image;
    private Graphics2D g;
    
    // game state Manager
    private GameStateManager gsm;
    
    public GamePanel() {
        super();
        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT* SCALE));
        setFocusable(true);
        requestFocus();
            
    }
    
    public void addNotify() {
        super.addNotify();
        if(thread == null) {
            thread = new Thread(this);
            addKeyListener(this);
            thread.start();
            
        }
        
    }
    public void init() {
        
        image= new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
                
        g = (Graphics2D) image.createGraphics();
        
        running = true;
        
        
        gsm = new GameStateManager();
    }
    
    
    public void run() {
        
        init();
        
        long start;
        long elapsed;
        long wait;
        
        
        //game loop
        while(running) {
            
            start = System.nanoTime()
;           
            update();
//line 79:
            draw();
            drawToScreen();
            
            elapsed = System.nanoTime() - start;
            
            wait = targetTime - elapsed / 1000000;
            if(wait < 0) wait = 5;
            
            try {
                Thread.sleep(wait);
            }
            catch(Exception e ) {
                e.printStackTrace();
            }
        }
        
    }
    
    private void update() {
        gsm.update();
        
    }
    private void draw() {
//line 102:
        gsm.draw(g);
        
    }
    private void drawToScreen() {
        Graphics g2 = getGraphics();
        g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
        g2.dispose();
    }
    
    public void keyTyped (KeyEvent key) {
        
    }
    public void keyPressed (KeyEvent key) {
        gsm.keyPressed (key.getKeyCode());
    }
    public void keyReleased (KeyEvent key) {
        gsm.keyReleased(key.getKeyCode());
    }
    
}

菜单:

package gameState;


import tileMap.Background;
import java.awt.*;
import java.awt.event.KeyEvent;

public class MenuState extends GameState{
    
    
    private Background bg;
    
    
    public int currentChoice = 0;
    private String[] options = {
            "Start",
            "Hilfe",
            "Verlassen"
            
    };
    
    private Color titleColor;
    private Font titleFont;
    
    private Font font;

    
    public MenuState(GameStateManager gsm) {
        
        this.gsm = gsm;
        
        try {
            
            bg = new Background("/Hintergünde/bg_v2.gif", 1);
            bg.setVector(-0.1, 0);
            
            titleColor = new Color(200, 0, 0);
            titleFont  = new Font("Times New Roman", Font.PLAIN, 28);
            
        font = new Font ("Times New Roman", Font.BOLD, 14);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public void init () {}
    public void update () {
        bg.update();
    }
    
    public void draw (Graphics2D g) {
        
        //Hintergrund
        bg.draw(g);
        
        //Titel
        g.setColor(titleColor);
        g.setFont(titleFont);
        g.drawString("Fred on the run", 80, 70);
        
        //Menü
        g.setFont(font);
        for(int i = 0; i < options.length; i++) {
            if(i == currentChoice) {
                g.setColor(Color.WHITE);
            }
            else {
                g.setColor(Color.LIGHT_GRAY);
            }
            g.drawString(options[i], 145, 140 + i * 15);
        }
        
    }
    
    private void select() {
        if(currentChoice == 0) {
            gsm.setState(GameStateManager.LEVEL1STATE);
        }
        if(currentChoice == 1) {
            //Hilfe
        }
        if(currentChoice == 2) {
            System.exit(0);
        }
    }
    
    
    public void keyPressed(int k) {
        if(k == KeyEvent.VK_ENTER) {
            select();
        }
        if(k == KeyEvent.VK_UP) {
            currentChoice--;
            if(currentChoice == -1) {
                currentChoice = options.length -1;
                
            }
        }
        if(k == KeyEvent.VK_DOWN) {
            currentChoice++;
            if(currentChoice == options.length) {
                    currentChoice = 0;
            }
            
        }
    }
    public void keyReleased(int k) {}
    
}

Level1阶段:

package gameState;


import main.GamePanel;
import tileMap.*;


import java.awt.*;


public class Level1State extends GameState {
    
    private TileMap tileMap;

    public Level1State(GameStateManager gsm) {
        this.gsm = gsm;
        init();
    }
    public void init() {
        tileMap = new TileMap(30);
        tileMap.loadTiles("/Tilesets/grasstileset.gif");
        tileMap.loadMap("/Maps/level1-1.map");
        tileMap.setPosition(0, 0);
        
    }
    public void update() {
        
        
    }
    public void draw(Graphics2D g) {
        
        //clear Screen
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, GamePanel.WIDTH, GamePanel.HEIGHT);
        
        
        //draw tile map
//line 38:
    tileMap.draw(g);
    }
    public void keyPressed(int k) {
        
        
    }
    public void keyReleased(int k) {
        
        
    }
}

瓷砖地图:

package tileMap;

import java.awt.*;
import java.awt.image.*;


import java.io.*;
import javax.imageio.ImageIO;

import main.GamePanel;




public class TileMap {
    //Position:
    private double x;
    private double y;
    
    //bounds
    private int xmin;
    private int ymin;
    private int xmax;
    private int ymax;
    
    private double tween; 
    
    
    //Karte
    private int[][] map;
    private int tileSize;
    private int numRows;
    private int numCols;
    private int width;
    private int height;
    
    //tileset
    private BufferedImage tileset;
    private int numTilesAcross;
    private Tile[][] tiles;
    
    
    //zeichnen
    private int rowOffset;
    private int colOffset;
    private int numRowsToDraw;
    private int numColsToDraw;
    
    public TileMap(int tileSize) {
        this.tileSize = tileSize;
        numRowsToDraw = GamePanel.HEIGHT / tileSize +2;
        numColsToDraw = GamePanel.WIDTH / tileSize +2;
        tween = 0.07;
    }
    
    public void loadTiles(String s) {
        
        try {
            
            tileset = ImageIO.read(getClass().getResource(s));
            numTilesAcross = tileset.getWidth() / tileSize;
            tiles = new Tile[2][numTilesAcross];
            
            
            BufferedImage subimage;
            for(int col = 0; col < numTilesAcross; col++) {
                subimage = tileset.getSubimage(col * tileSize, 0, tileSize, tileSize);
                
                tiles[0][col] = new Tile (subimage, Tile.NORMAL);
                subimage = tileset.getSubimage(col * tileSize, tileSize, tileSize, tileSize);
                tiles[1] [col] = new Tile(subimage, Tile.BLOCKED);
                
            }
        }
        catch(Exception e)  {
            e.printStackTrace();
        }
    }
    public void loadMap(String s) {
        
        try {
            
            InputStream in = getClass().getResourceAsStream(s);
            BufferedReader br = new BufferedReader(
                        new InputStreamReader(in)
                    );
                    
            numCols = Integer.parseInt(br.readLine());
            numRows = Integer.parseInt(br.readLine());
            map = new int[numRows][numCols];
            width  = numCols * tileSize;
            height = numRows * tileSize;
            
            
            String delims = "\s+";
            for(int row = 0; row < numRows; row++) {
                String line = br.readLine();
                String[] tokens = line.split(delims);
                for(int col = 0; col < numCols; col++) {
                    map[row][col] = Integer.parseInt(tokens[col]);
                }
                
                
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        
    }
    
    public int getTileSize() {return tileSize; }
    public int getx() { return (int)x; } 
    public int gety() { return (int)y; } 
    public int getWidth() { return width; }
    public int getHeight() { return height; }
    
    public int getType(int row, int col) {
        int rc = map [row] [col];
        
        int r = rc / numTilesAcross;
        int c = rc % numTilesAcross;
        return tiles[r] [c].getType();
        
        
    }
    
    public void setPosition(double x, double y) {
            
        this.x += (x - this.x) * tween;
        this.y += (y - this.y) * tween;
        
        fixBounds();
        
        colOffset = (int)-this.x /tileSize;
        rowOffset = (int)-this.y /tileSize;
    }
    
    private void fixBounds() {
        if(x < xmin) x = xmin;
        if(y < ymin) y = ymin;
        if(x > xmax) x = xmax;
        if(y > ymax) x = ymax;
        
    }
    
    public void draw(Graphics2D g) {
        
        for (int row = rowOffset; row < rowOffset + numRowsToDraw; row++) {
            
        
        for(
            int col = colOffset;
                col < colOffset + numColsToDraw; col++) {
            
            if(col >= numCols) break;
            
        //line 158: 
            if(map[row][col] == 0) continue;
            
            int rc = map[row][col];
            int r = rc / numTilesAcross;
            int c = rc % numTilesAcross;
            
            g.drawImage(tiles[r][c].getImage(),
                    (int)x + col * tileSize,
                    (int)y + row * tileSize, null);
        }   
        }
            
    }
    
}

平铺:

package tileMap;

import java.awt.image.BufferedImage;






public class Tile {

    private BufferedImage image;
    private int type; 
    
    //tile Typen
    public static final int NORMAL  = 0;
    public static final int BLOCKED = 1;
     
    
    public Tile(BufferedImage image, int type) {
        this.image = image;
        this.type  = type;
        
    }
    
    public BufferedImage getImage() { return image; }
    public  int getType() { return type; }
    
    
}

最后一个,游戏状态管理器:

package gameState;

import java.util.ArrayList;


public class GameStateManager {

    private ArrayList <GameState> gameStates;
    private int currentState;
    
    public static final int MENUSTATE = 0;
    public static final int LEVEL1STATE = 1;
    
    public GameStateManager() {
        
        gameStates= new ArrayList <GameState>();
        
        currentState = MENUSTATE;
        gameStates.add(new MenuState(this));
        gameStates.add(new Level1State(this));
    }
    
    public void setState(int state) {
        currentState = state;
        gameStates.get(currentState).init();
    }
    
    public void update () {
            gameStates.get(currentState).update();
            
    }
    public void draw(java.awt.Graphics2D g) {
            gameStates.get(currentState).draw(g);
        
    }
    
    public void keyPressed(int k) {
        gameStates.get(currentState).keyPressed(k);
        
        
    }
    
    public void keyReleased(int k) {
        gameStates.get(currentState).keyReleased(k);
        
    }
    
    
    
    
    
}

我只能根据您提供的信息进行猜测,但我认为问题可能在于 TileMap 绘制方法,特别是“行”的值。我看到 row 的值可能超出数组的范围。尝试添加此约束(与对列所做的相同)并查看是否有帮助:

if(row >= numRows) break;