线程"AWT-EventQueue-0" java.lang.ArrayIndexOutOfBounds异常:132



我正在尝试制作一款游戏,在这个阶段它所做的只是创建一个你可以移除或放置的贴图板。然而,当我将网格扩展到任何高于128的值时,它就崩溃了。然而,只有当宽度较大时才会发生这种情况。如果高度更大,那么它会在第一个网格下面形成第二个网格,这就有点奇怪了。下面是我的代码和我得到的错误的堆栈跟踪。

你可以通过改变Game.java下的世界设置中的值来看到它应该如何工作。(同样,如果width是更大的数字,并且它乘以超过128,这就是导致错误的原因。)

Game.java

package engine;
import java.awt.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class Game extends JPanel{
private Thread thread;

//world settings
static int worldWidth = 11;
static int worldHeight = 12;

public int w = worldWidth;
public int h = worldHeight;

//window settings
private static int windowWidth = 800;
private static int windowHeight = 600;
private static String windowTitle = "Game";

//tile settings
public static int tileSize = 50;

public static int tilex;
public static int tiley;

private static byte[] tiles;
public void paint(Graphics g) {
super.paintComponent(g);
//set background color
setBackground(new Color(0,128,255));
//set color and area of shape
g.setColor(new Color(0,255,0));

//checks array every repaint for modified tiles
for(int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int i = y + (x * w);
if (tiles[i] == 1) {
tilex = x * tileSize;
tiley = y * tileSize;
g.fillRect(tilex, tiley, tileSize, tileSize);
}
}
}
//Pointer/selector
}
public static void main(String[] args) throws InterruptedException {
new Game();
}

public void init() {
new Window(windowWidth, windowHeight, windowTitle, this);
Window.running = true;

thread = new Thread();
thread.start();

generate();
}

public void terminate() {
System.exit(0);
}

public Game() throws InterruptedException {
try {
init();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.toString(), "Failed to start " + windowTitle, JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
while(Window.running) {
Thread.sleep(1);
//closes game if escape is pressed or if window is closed (handled in window class)
if (!Window.running) {
System.out.println("Closing " + windowTitle);
terminate();
}
//render
repaint();
}
}

public void generate() {
tiles = new byte[w * h];
for(int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int i = y + (x * w);
//1 = tile present, 0 = not present
tiles[i] = (byte) 1;
}
}
}

public static void changeSquare() {
if (GameListener.mouseButton == 3 && GameListener.modifyBlock) {
tiles[GameListener.byteToModify] = 1;
} else if (GameListener.mouseButton == 1 && GameListener.modifyBlock){
tiles[GameListener.byteToModify] = 0;
}
}
}

Window.java

package engine;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class Window {
public static boolean running = false;
public Window(int width, int height, String title, Game game) {
//creates and displays window
JFrame frame = new JFrame(title);

KeyListener keylistener = new KeyListener() {
@Override
public void keyPressed(KeyEvent keyEvent) {
GameListener.keyListener(keyEvent);
}
@Override
public void keyReleased(KeyEvent keyEvent) {

}
@Override
public void keyTyped(KeyEvent keyEvent) {

}
};

MouseListener mouselistener = new MouseListener() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {

}
@Override
public void mouseEntered(MouseEvent mouseEvent) {

}
@Override
public void mouseExited(MouseEvent mouseEvent) {

}
@Override
public void mousePressed(MouseEvent mouseEvent) {
GameListener.mouseListener(mouseEvent);
Game.changeSquare();
}
@Override
public void mouseReleased(MouseEvent mouseEvent) {

}
};

MouseMotionListener mousemotionlistener = new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent mouseMotionEvent) {
GameListener.mouseMotionListener(mouseMotionEvent);
}
@Override
public void mouseMoved(MouseEvent arg0) {

}
};
//listens for window close and sends back to game loop to terminate
frame.addWindowListener(new WindowAdapter() {

@Override
public void windowClosing(WindowEvent e) {
running = false;
}
});
frame.getContentPane().addKeyListener(keylistener);
frame.getContentPane().addMouseListener(mouselistener);
frame.getContentPane().addMouseMotionListener(mousemotionlistener);
frame.setPreferredSize(new Dimension(width, height));
frame.add(game);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}

最后是GameListener.java

package engine;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
public class GameListener {
private static int tileX;
private static int tileY;
private static int xTries;
private static int yTries;

private static int tileXM;
private static int tileYM;
private static int xTriesM;
private static int yTriesM;
public static int byteToModify;
public static int mouseButton;
public static boolean modifyBlock;

public static boolean drawSelector;
public static int byteToDrawSelector;

public static void keyListener(KeyEvent e) {
int code = e.getKeyCode();

//put key if statements here (for example escape to close

//use for testing key name when adding a new if statement 
//String character = KeyEvent.getKeyText(code);
//System.out.println("Character: " + KeyEvent.getKeyText(code));
//System.out.println("Code: " + code);

//get key codes at keycode.info

//closes game on escape
if (code == 27) {
//escape
Window.running = false;
}
//movement
// if (code == 87) {
//W
//  Game.y = Game.y - 100;
//      }
//  if (code == 65) {
//A
//   Game.x = Game.x - 100;
//  }
//  if (code == 83) {
//S
//   Game.y = Game.y + 100;
//  }
// if (code == 68) {
//D
//Game.x = Game.x + 100;
// }
}

public static void mouseListener(MouseEvent e) {
//System.out.println(e.getX());
//System.out.println(e.getY());
//System.out.println(e.getButton());

xTries = 0;
tileX = 0;
yTries = 0;
tileY = 0;
modifyBlock = true;

if (e.getX() < Game.tileSize) {

} else if (e.getX() > Game.tileSize && e.getX() < (Game.tileSize * Game.worldWidth)) {
for (int i = Game.tileSize; i<e.getX(); i = i + Game.tileSize) {
xTries++;
}
//System.out.println(xTries);
tileX = xTries;
} else {
System.err.println("User clicked outside of world");
modifyBlock = false;
}
if (e.getY() < Game.tileSize) {
} else if (e.getY() > Game.tileSize && e.getY() < (Game.tileSize * Game.worldHeight)) {
for (int i = Game.tileSize; i<e.getY(); i = i + Game.tileSize) {
yTries++;
}
//System.out.println(yTries);
tileY = yTries;
} else {
System.err.println("User clicked outside of world");
modifyBlock = false;
}
if (e.getButton() == MouseEvent.BUTTON1) {
mouseButton = 1;
} else if (e.getButton() == MouseEvent.BUTTON3) {
mouseButton = 3;
}
byteToModify = tileY+(tileX * Game.worldWidth);

//System.out.println(tileX);
//System.out.println(tileY);
//System.out.println(byteToModify);
}

public static void mouseMotionListener(MouseEvent e) {
//System.out.println(e.getX());
//System.out.println(e.getY());
xTriesM = 0;
tileXM = 0;
yTriesM = 0;
tileYM = 0;
drawSelector = true;

if (e.getX() < Game.tileSize) {

} else if (e.getX() > Game.tileSize && e.getX() < (Game.tileSize * Game.worldWidth)) {
for (int i = Game.tileSize; i<e.getX(); i = i + Game.tileSize) {
xTriesM++;
}
//System.out.println(xTries);
tileXM = xTriesM;
} else {
drawSelector = false;
}
if (e.getY() < Game.tileSize) {
} else if (e.getY() > Game.tileSize && e.getY() < (Game.tileSize * Game.worldHeight)) {
for (int i = Game.tileSize; i<e.getY(); i = i + Game.tileSize) {
yTriesM++;
}
//System.out.println(yTries);
tileYM = yTriesM;
} else {
drawSelector = false;
}
byteToDrawSelector = tileYM+(tileXM* Game.worldWidth);
}
}

这是我在加载游戏时得到的错误。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 132
at engine.Game.paint(Game.java:45)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 132
at engine.Game.paint(Game.java:45)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at javax.swing.RepaintManager$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1200(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

它说问题在Game.java第45行,但我真的不明白是什么原因导致的。

你在for循环中的计算是错误的。

首先,w(类Game中的成员变量)实际上表示[二维]网格中的列数,h(类Game中的另一个成员变量)表示行数。您在嵌套的for循环中使用了错误的方式。所以不用

for(int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {

你应该有

for(int x = 0; x < h; x++) {
for (int y = 0; y < w; y++) {

所以我只更改了Game类的代码。为了完整起见,下面是类的完整代码,并进行了上述更改。

package engine;
import java.awt.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class Game extends JPanel {
private Thread thread;
// world settings
static int worldWidth = 12;
static int worldHeight = 11;
public int w = worldWidth;
public int h = worldHeight;
// window settings
private static int windowWidth = 800;
private static int windowHeight = 600;
private static String windowTitle = "Game";
// tile settings
public static int tileSize = 50;
public static int tilex;
public static int tiley;
private static byte[] tiles;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// set background color
setBackground(new Color(0, 128, 255));
// set color and area of shape
g.setColor(new Color(0, 255, 0));
// checks array every repaint for modified tiles
for (int x = 0; x < h; x++) {
for (int y = 0; y < w; y++) {
int i = y + (x * w);
if (tiles[i] == 1) {
tilex = x * tileSize;
tiley = y * tileSize;
g.fillRect(tilex, tiley, tileSize, tileSize);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
new Game();
}
public void init() {
new Window(windowWidth, windowHeight, windowTitle, this);
Window.running = true;
thread = new Thread();
thread.start();
generate();
}
public void terminate() {
System.exit(0);
}
public Game() throws InterruptedException {
try {
init();
}
catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e.toString(), "Failed to start " + windowTitle,
JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
while (Window.running) {
Thread.sleep(1);
// closes game if escape is pressed or if window is closed (handled in window
// class)
if (!Window.running) {
System.out.println("Closing " + windowTitle);
terminate();
}
// render
repaint();
}
}
public void generate() {
tiles = new byte[w * h];
for (int x = 0; x < h; x++) {
for (int y = 0; y < w; y++) {
int i = y + (x * w);
// 1 = tile present, 0 = not present
tiles[i] = (byte) 1;
}
}
}
public static void changeSquare() {
if (GameListener.mouseButton == 3 && GameListener.modifyBlock) {
tiles[GameListener.byteToModify] = 1;
}
else if (GameListener.mouseButton == 1 && GameListener.modifyBlock) {
tiles[GameListener.byteToModify] = 0;
}
}
}

您还应该注意到您的设计包含循环依赖关系,因为三个类Game,GameListenerWindow中的每一个都引用了其他两个类。这通常是个糟糕的设计。

这个显示中没有行号,也不会计算行数。检查第45行中的代码。我猜是

if (tiles[i] == 1) {

当应用程序崩溃时,你知道它正在尝试访问索引132。检查数组的大小。我猜是11x12=132项,从0到131编号。

有没有可能你对i的计算是错误的?

最新更新