我正在尝试制作一个游戏,在这个阶段它所做的就是创建一个可以移除或放置的瓷砖板。但是,当我将网格扩展到 128 以上的任何值时,它会崩溃。然而,只有当宽度是更大的数字时才会发生。如果高度更大,那么它会在第一个网格下方创建第二个网格,这会变得有点奇怪。下面是我的代码和我得到的错误的堆栈跟踪。
您可以通过更改世界设置中的值来查看它应该如何运行Game.java
。(同样,如果宽度是更大的数字并且它乘以超过 128,这就是导致错误的原因。)
游戏.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;
}
}
}
窗口.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
( class 中的成员变量Game
)实际上表示 [二维] 瓷砖网格中的列数,h
( class 中的另一个成员变量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++) {
所以我只改变了 class 的代码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
,GameListener
以及Window
参考其他两个。这通常是一个糟糕的设计。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句