I'm creating a pacman game, and I'm getting an exception that I can't figure out:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -11
at p.PacBoard.moveGhosts(PacBoard.java:207)
And here is where the logic of my game is (I marked off the line that has thrown the exception):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class PacBoard extends JPanel implements ActionListener {
Dimension d;
String s = "Press s to start.";;
Font small = new Font("Helvetica", Font.BOLD, 14);
FontMetrics metr = this.getFontMetrics(small);
Image ii;
Color dotcolor = new Color(192, 192, 0);
Color mazecolor;
boolean ingame = false;
boolean dying = false;
final int blocksize = 24;
final int nrofblocks = 15;
final int scrsize = nrofblocks * blocksize;
final int pacanimdelay = 2;
final int pacmananimcount = 4;
final int maxghosts = 6;
final int pacmanspeed = 6;
int pacanimcount = pacanimdelay;
int pacanimdir = 1;
int pacmananimpos = 0;
int nrofghosts = 4;
int pacsleft, score;
int deathcounter;
int[] dx, dy;
int[] ghostx, ghosty, ghostdx, ghostdy, ghostspeed;
Image ghost;
Image pacman1, pacman2up, pacman2left, pacman2right, pacman2down;
Image pacman3up, pacman3down, pacman3left, pacman3right;
Image pacman4up, pacman4down, pacman4left, pacman4right;
int pacmanx, pacmany, pacmandx, pacmandy;
int reqdx, reqdy, viewdx, viewdy;
final short leveldata[] =
{ 3, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 22, 3, 10, 6,
1, 25, 24, 16, 16, 16, 16, 16, 16, 16, 16, 20, 5, 15, 5,
1, 0, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 9, 10, 12,
19, 18, 18, 16, 16, 16, 24, 16, 24, 16, 16, 24, 18, 18, 22,
17, 16, 16, 16, 16, 28, 0, 21, 0, 17, 20, 0, 17, 16, 20,
17, 16, 16, 16, 28, 0, 19, 20, 0, 25, 28, 0, 17, 16, 20,
17, 16, 16, 28, 0, 19, 16, 20, 0, 0, 0, 0, 17, 16, 20,
17, 16, 20, 0, 27, 16, 16, 16, 18, 18, 22, 0, 17, 16, 20,
17, 16, 16, 22, 0, 25, 16, 16, 16, 16, 20, 0, 17, 16, 20,
17, 16, 16, 16, 22, 0, 25, 16, 16, 16, 20, 0, 17, 16, 20,
17, 16, 16, 16, 16, 22, 0, 17, 16, 16, 20, 0, 17, 16, 20,
25, 16, 24, 16, 16, 16, 18, 16, 16, 16, 16, 18, 24, 24, 28,
1, 21, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 0, 8, 12,
9, 29, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 0, 10, 14,
9, 15, 27, 24, 24, 24, 24, 24, 24, 24, 24, 28, 8, 10, 14};
final int validspeeds[] = {1, 2, 3, 4, 5, 6};
final int maxspeed = 6;
int currentspeed = 3;
short[] screendata;
Timer timer;
public PacBoard() {
GetImages();
addKeyListener(new TAdapter());
screendata = new short[nrofblocks * nrofblocks];
mazecolor = new Color(255, 0, 5);
setFocusable(true);
d = new Dimension(400, 400);
setBackground(Color.black);
setDoubleBuffered(true);
ghostx = new int[maxghosts];
ghostdx = new int[maxghosts];
ghosty = new int[maxghosts];
ghostdy = new int[maxghosts];
ghostspeed = new int[maxghosts];
dx = new int[4];
dy = new int[4];
timer = new Timer(40, this);
timer.start();
}
public void addNotify() {
super.addNotify();
GameInit();
}
public void DoAnim() {
pacanimcount--;
if (pacanimcount <= 0) {
pacanimcount = pacanimdelay;
pacmananimpos = pacmananimpos + pacanimdir;
if (pacmananimpos == (pacmananimcount - 1) || pacmananimpos == 0)
pacanimdir = -pacanimdir;
}
}
public void PlayGame(Graphics2D g2d) {
if (dying) {
Death();
} else {
MovePacMan();
DrawPacMan(g2d);
moveGhosts(g2d);
CheckMaze();
}
}
public void ShowIntroScreen(Graphics2D g2d) {
g2d.setColor(new Color(0, 32, 48));
g2d.fillRect(50, scrsize / 2 - 30, scrsize - 100, 50);
g2d.setColor(Color.white);
g2d.drawRect(50, scrsize / 2 - 30, scrsize - 100, 50);
g2d.setColor(Color.white);
g2d.setFont(small);
g2d.drawString(s, (scrsize - metr.stringWidth(s)) / 2, scrsize / 2);
}
public void DrawScore(Graphics2D g) {
int i;
String s;
g.setFont(small);
g.setColor(new Color(96, 128, 255));
s = "Score: " + score;
g.drawString(s, scrsize / 2 + 96, scrsize + 16);
for (i = 0; i < pacsleft; i++) {
g.drawImage(pacman3left, i * 28 + 8, scrsize + 1, this);
}
}
public void CheckMaze() {
short i = 0;
boolean finished = true;
while (i < nrofblocks * nrofblocks && finished) {
if ((screendata[i] & 48) != 0)
finished = false;
i++;
}
if (finished) {
score += 50;
if (nrofghosts < maxghosts)
nrofghosts++;
if (currentspeed < maxspeed)
currentspeed++;
LevelInit();
}
}
public void Death() {
pacsleft--;
if (pacsleft == 0)
ingame = false;
LevelContinue();
}
public void moveGhosts(Graphics2D g2d) {
short i;
int pos;
int count;
for (i = 0; i < nrofghosts; i++) {
if (ghostx[i] % blocksize == 0 && ghosty[i] % blocksize == 0) {
pos = ghostx[i] / blocksize + nrofblocks * (int)(ghosty[i] / blocksize);
count = 0;
//line that causes problems below
if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
//line that causes problems above
dx[count] = -1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 2) == 0 && ghostdy[i] != 1) {
dx[count] = 0;
dy[count] = -1;
count++;
}
if ((screendata[pos] & 4) == 0 && ghostdx[i] != -1) {
dx[count] = 1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 8) == 0 && ghostdy[i] != -1) {
dx[count] = 0;
dy[count] = 1;
count++;
}
if (count == 0) {
if ((screendata[pos] & 15) == 15) {
ghostdx[i] = 0;
ghostdy[i] = 0;
} else {
ghostdx[i] = -ghostdx[i];
ghostdy[i] = -ghostdy[i];
}
} else {
count = (int)(Math.random() * count);
if (count > 3)
count = 3;
ghostdx[i] = dx[count];
ghostdy[i] = dy[count];
}
}
ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
DrawGhost(g2d, ghostx[i] + 1, ghosty[i] + 1);
if (pacmanx > (ghostx[i] - 12) && pacmanx < (ghostx[i] + 12) &&
pacmany > (ghosty[i] - 12) && pacmany < (ghosty[i] + 12) &&
ingame) {
dying = true;
deathcounter = 64;
}
}
}
public void DrawGhost(Graphics2D g2d, int x, int y) {
g2d.drawImage(ghost, x, y, this);
}
public void MovePacMan() {
int pos;
short ch;
if (reqdx == -pacmandx && reqdy == -pacmandy) {
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
if (pacmanx % blocksize == 0 && pacmany % blocksize == 0) {
pos = pacmanx / blocksize + nrofblocks * (int)(pacmany / blocksize);
ch = screendata[pos];
if ((ch & 16) != 0) {
screendata[pos] = (short)(ch & 15);
score++;
}
if (reqdx != 0 || reqdy != 0) {
if (!((reqdx == -1 && reqdy == 0 && (ch & 1) != 0) ||
(reqdx == 1 && reqdy == 0 && (ch & 4) != 0) ||
(reqdx == 0 && reqdy == -1 && (ch & 2) != 0) ||
(reqdx == 0 && reqdy == 1 && (ch & 8) != 0))) {
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
}
// Check for standstill
if ((pacmandx == -1 && pacmandy == 0 && (ch & 1) != 0) ||
(pacmandx == 1 && pacmandy == 0 && (ch & 4) != 0) ||
(pacmandx == 0 && pacmandy == -1 && (ch & 2) != 0) ||
(pacmandx == 0 && pacmandy == 1 && (ch & 8) != 0)) {
pacmandx = 0;
pacmandy = 0;
}
}
pacmanx = pacmanx + pacmanspeed * pacmandx;
pacmany = pacmany + pacmanspeed * pacmandy;
}
public void DrawPacMan(Graphics2D g2d) {
if (viewdx == -1)
DrawPacManLeft(g2d);
else if (viewdx == 1)
DrawPacManRight(g2d);
else if (viewdy == -1)
DrawPacManUp(g2d);
else
DrawPacManDown(g2d);
}
public void DrawPacManUp(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2up, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3up, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4up, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManDown(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2down, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3down, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4down, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManLeft(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2left, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3left, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4left, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManRight(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2right, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3right, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4right, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawMaze(Graphics2D g2d) {
short i = 0;
int x, y;
for (y = 0; y < scrsize; y += blocksize) {
for (x = 0; x < scrsize; x += blocksize) {
g2d.setColor(mazecolor);
g2d.setStroke(new BasicStroke(2));
if ((screendata[i] & 1) != 0) // draws left
{
g2d.drawLine(x, y, x, y + blocksize - 1);
}
if ((screendata[i] & 2) != 0) // draws top
{
g2d.drawLine(x, y, x + blocksize - 1, y);
}
if ((screendata[i] & 4) != 0) // draws right
{
g2d.drawLine(x + blocksize - 1, y, x + blocksize - 1,
y + blocksize - 1);
}
if ((screendata[i] & 8) != 0) // draws bottom
{
g2d.drawLine(x, y + blocksize - 1, x + blocksize - 1,
y + blocksize - 1);
}
if ((screendata[i] & 16) != 0) // draws point
{
g2d.setColor(dotcolor);
g2d.fillRect(x + 11, y + 11, 2, 2);
}
i++;
}
}
}
public void GameInit() {
pacsleft = 3;
score = 0;
LevelInit();
nrofghosts = 4;
currentspeed = 3;
}
public void LevelInit() {
int i;
for (i = 0; i < nrofblocks * nrofblocks; i++)
screendata[i] = leveldata[i];
LevelContinue();
}
public void LevelContinue() {
short i;
int dx = 1;
int random;
for (i = 0; i < nrofghosts; i++) {
ghosty[i] = 4 * blocksize;
ghostx[i] = 4 * blocksize;
ghostdy[i] = 0;
ghostdx[i] = dx;
dx = -dx;
random = (int)(Math.random() * (currentspeed + 1));
if (random > currentspeed)
random = currentspeed;
ghostspeed[i] = validspeeds[random];
}
pacmanx = 7 * blocksize;
pacmany = 11 * blocksize;
pacmandx = 0;
pacmandy = 0;
reqdx = 0;
reqdy = 0;
viewdx = -1;
viewdy = 0;
dying = false;
}
public void GetImages()
{
ghost = new ImageIcon(PacBoard.class.getResource("../pacpix/ghost.gif")).getImage();
pacman1 = new ImageIcon(PacBoard.class.getResource("../pacpix/pacman.png")).getImage();
pacman2up = new ImageIcon(PacBoard.class.getResource("../pacpix/up1.png")).getImage();
pacman3up = new ImageIcon(PacBoard.class.getResource("../pacpix/up2.png")).getImage();
pacman4up = new ImageIcon(PacBoard.class.getResource("../pacpix/up3.png")).getImage();
pacman2down = new ImageIcon(PacBoard.class.getResource("../pacpix/down1.png")).getImage();
pacman3down = new ImageIcon(PacBoard.class.getResource("../pacpix/down2.png")).getImage();
pacman4down = new ImageIcon(PacBoard.class.getResource("../pacpix/down3.png")).getImage();
pacman2left = new ImageIcon(PacBoard.class.getResource("../pacpix/left1.png")).getImage();
pacman3left = new ImageIcon(PacBoard.class.getResource("../pacpix/left2.png")).getImage();
pacman4left = new ImageIcon(PacBoard.class.getResource("../pacpix/left3.png")).getImage();
pacman2right = new ImageIcon(PacBoard.class.getResource("../pacpix/right1.png")).getImage();
pacman3right = new ImageIcon(PacBoard.class.getResource("../pacpix/right2.png")).getImage();
pacman4right = new ImageIcon(PacBoard.class.getResource("../pacpix/right3.png")).getImage();
}
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
g2d.fillRect(0, 0, d.width, d.height);
DrawMaze(g2d);
DrawScore(g2d);
DoAnim();
if (ingame){
PlayGame(g2d);
}
else{
ShowIntroScreen(g2d);
}
g.drawImage(ii, 5, 5, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (ingame)
{
if (key == KeyEvent.VK_LEFT)
{
reqdx=-1;
reqdy=0;
}
else if (key == KeyEvent.VK_RIGHT)
{
reqdx=1;
reqdy=0;
}
else if (key == KeyEvent.VK_UP)
{
reqdx=0;
reqdy=-1;
}
else if (key == KeyEvent.VK_DOWN)
{
reqdx=0;
reqdy=1;
}
else if (key == KeyEvent.VK_ESCAPE && timer.isRunning())
{
ingame=false;
}
else if (key == KeyEvent.VK_PAUSE) {
if (timer.isRunning())
timer.stop();
else timer.start();
}
}
else
{
if (key == 's' || key == 'S')
{
ingame=true;
GameInit();
}
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == Event.LEFT || key == Event.RIGHT ||
key == Event.UP || key == Event.DOWN)
{
reqdx=0;
reqdy=0;
}
}
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Sorry I know that's a lot of code but I'm not sure where the problem is being created. Here is the line that it is being caught at:
if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
I know it has to be increasing or decreasing the size of the array to an illegal number, but where? And why? That's what I don't understand. Oh, and I got the exception in my output window about 10 times, not sure why though. Would this mean it's getting increased in one of my for loops?
Thanks to anyone who will help, and I will provide more information as needed.
To compile:
import javax.swing.JFrame;
public class Pacman extends JFrame
{
public Pacman()
{
add(new PacBoard());
setTitle("Pacman");
setSize(380, 420);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Pacman();
}
}