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;
我最近几天在做一个小游戏,已经取得了巨大的进步。现在我遇到了一个问题,我看不到需要解决的问题。它说
"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;