IndexOutOfBounds exception?

Hi all,

I have been working on this game as part of a small piece of coursework for my course, however I have run into a problem. When the game is run, I get an Index out of Bounds Exception, but the exception is not always the same. It could be 11, 15, 4, 7, anything. Any ideas??? This is my code... Main Code

import ddf.minim.*;

//Declare audio
Minim minim;
AudioSample projectilesound;
AudioSample explosion;
AudioPlayer bgmusic;
AudioPlayer menumusic;

//Delcar classes
Player player;
Background background;
Projectile projectile;
Paused paused;
startMenu menu;
Asteroids asteroids;
gameOver gameover;

//Arrays
ArrayList shots ; //where the shots are stored
ArrayList asteroid;

//Boolean controllers
boolean mouseClick = false; //prevent menu clicking
boolean canPause = false; //prevent menu pausing
boolean asteroidStart = false;//prevent asteroids from running on menu


float[] x = new float[1000]; //x values for stars
float[] y = new float[1000]; //y values for stars
float[] speed = new float [1000]; //speed for stars

int time;
int lives = 1;

PImage imnorm3;
PImage imtitle;

int getRandomY()
{
  return int(random(264, 934));
}


int[] asteroidy = { getRandomY(), getRandomY(), getRandomY(), getRandomY(), getRandomY(), 
  getRandomY(), getRandomY(), getRandomY(), getRandomY(), getRandomY() };
int[] asteroidx = { 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600 };

void setup() {
  size(1600, 1200, P2D);
  smooth();
  background(0);
  stroke(255);
  frameRate(60);

  //Initialize Audio
  minim = new Minim(this);
  bgmusic = minim.loadFile("bgmusic.mp3", 2048);
  menumusic = minim.loadFile("menumusic.mp3", 2048);
  projectilesound = minim.loadSample("projectilesound.wav", 2048);
  explosion = minim.loadSample("Explosion.wav", 2048);

  //Arrays
  shots = new ArrayList();
  asteroid = new ArrayList();


  //Initialize Classes
  imnorm3 = loadImage("asteroids.png");
  imtitle = loadImage("AsteroidDefender.png");
  player = new Player(0, 600);
  background = new Background();
  menu = new startMenu();
  paused = new Paused();
  gameover = new gameOver();

  //While loop to create stars
  int i = 0;
  while (i < 1000) {
    x[i] = random(0, width);
    y[i] = random(205, 995);
    speed[i] = random(1, 5);
    i = i + 1;
  }
}
void draw() {
  rect(0, 200, width, 800);
  background.display();
  menu.menuRun();
  fill(0, 75);
  noStroke();
  fill(255);
  stroke(200);
  line(0, 200, width, 200);
  line(0, 1000, width, 1000);
  strokeWeight(3);
  player.run();
  textSize(28);
  image(imtitle, 600, 10);
  text("Score: " + player.score, 32, 1050);
  text("Lives: " + lives, 32, 1100);
  if (asteroidStart == true) {
    spawn();
    move();
    display();
    collision();
    movePJ();
    displayPJ();
    time++;
    lose();
  }
  if (gameover.isOver == true) {
    gameover.run();
  }
}

//Starts the game
void keyPressed() {
  if (key == ENTER) {
    noCursor();
    mouseClick = true;
    canPause = true;
    menu.runMenu = false;
    player.runPlayer = true;
    asteroidStart = true;
    menumusic.pause();
    bgmusic.setGain(-10);
    bgmusic.loop();

    //Pauses the game
  }
  if (key == 'p') {
    if (canPause == true) {
      paused.ispaused = true;
      player.runPlayer = false;
      paused.run();
    }
  }
  //Mutes the music
  if (key == 'm') {
    bgmusic.mute();
  }
  //Unmutes the music
  if (key == 'u') {
    bgmusic.unmute();
  }
}
//Populates the array "shots" with new objects modelled after the "Projectile" class
void mousePressed() {
  if (mouseClick == true) {
    Projectile pj = new Projectile(player.x, (player.y1+16));
    shots.add(pj);
    pj = null;
    projectilesound.trigger();
  }
}
//Calls the shot() method from the class for every projectile
void movePJ() {
  for (int i = 0; i < shots.size(); i ++) {
    Projectile pj = (Projectile)shots.get(i);
    pj.shot();
    pj = null;
  }
}
//Calls the display() method from the class for every projectile
void displayPJ() {
  for (int i = 0; i < shots.size(); i++) {
    Projectile pj = (Projectile)shots.get(i);
    pj.display();
    pj = null;
  }
}
//Asteroid Class
public class Asteroids {
  //GLOBAL VARIABLES
  float a = 0;
  float x;
  float y;
  PImage imnorm3;


  //CONSTRUCTOR
  Asteroids( float ax, float ay) {
    x = ax;
    y = ay;
    imnorm3 = loadImage("asteroids.png");
  }
  void display() {
    image(imnorm3, x, y);
  }
  void move() {
    x -=5;
  }
}
void spawn() {
  if (time == 30) { // Delays asteroid spawn

    time = 0;
    Asteroids at = new Asteroids(2500, int(random(200, 950)));
    asteroid.add(at);
    at = null;
  }
}
void move() {
  for (int i = 0; i < asteroid.size(); i++) {
    Asteroids at = (Asteroids)asteroid.get(i);
    at.move();
  }
}
void display() {
  for (int i = 0; i < asteroid.size(); i ++) {
    Asteroids at = (Asteroids)asteroid.get(i);
    at.display();
    at = null;
  }
}
//Detects collision between asteroid and projectile
void collision() {
  for (int i = 0; i < asteroid.size(); i++) {
    for (int j = 0; j < shots.size(); j++) {
      Projectile pj = (Projectile)shots.get(j);
      Asteroids at = (Asteroids)asteroid.get(i);
      if (pj.x < at.x - 16 && pj.y > at.y -16 && pj.y <= at.y + 16) {
        asteroid.remove(i);
        shots.remove(j);
        explosion.trigger();
        player.score += 1 ;
      }
    }
  }
}
void lose() {
  for (int i = 0; i < asteroid.size(); i++) {
    Asteroids at = (Asteroids)asteroid.get(i);
    if (at.x < 0) {
      lives = 0;
      gameover.isOver = true;
    }
  }
}

Gameover Class

public class gameOver {
  //GLOBAL VARIABLES
  boolean isOver = false;

  //CONSTRUCTOR


  //FUNCTIONS
  void run() {
    if (isOver == true) {
      if (lives == 0) {

        mouseClick = false;
        canPause = false;
        player.runPlayer = false;
        asteroidStart = false;
        bgmusic.pause();
        menumusic.play();
        stroke(0);
        textSize(48);
        text("GAME OVER", 600, 600);
        text("Your Score: " + player.score,600,650);
        text("Please exit game", 600, 700);
      }
    }
  }
}

**Startmenu - I know there is an issue with this displaying but I'm not worried about that at the moment.**

public class startMenu {
  //GLOBAL VARIABLES
  boolean runMenu = true;


  //CONSTRUCTORS



  //FUNCTIONS
  void menuRun() {
    if (runMenu == true) {
      stroke(0);
      textSize(48);
      text("WELCOME TO ASTEROID DEFENDER", 400, 600);
      text("Press Enter to start", 600, 700);
      text("Click to shoot. Use W and S to move up and down.", 250, 800);
      menumusic.play();
    }
  }
}

Paused

class Paused {
  //GLOBAL VARIABLES
  boolean ispaused = false;

  //CONSTRUCTOR (N/A)



  //FUNCTIONS
  void run() {
    if (ispaused == true) {
      bgmusic.pause();
      textdisplay();
    }
  }
  void textdisplay() {
    text(":::PAUSED:::", 800, 600);
  }
}

Player

public class Player {
  //GLOBAL VARIABLES
  boolean runPlayer = false;
  int x = 0;
  int y = 0;
  float y1 = 600;
  float yspeed = 10;
  PImage imnorm2;
  PImage imnorm4;
  int score;


  //CONSTRUSCTOR
  Player(int _x, int _y) {
    x = _x;
    y = _y;

    imnorm2 = loadImage("playership.png");
    imnorm4 = loadImage("playershipvert.png");
  }



  //FUNCTIONS
  void run() {
    if (runPlayer == true) {
      aim();
      display();
    }
  }
  void aim() {
    if (key == 's') {
      if (keyPressed) {
        y1 = y1 + yspeed;
      }
    }
    if (key == 'w') {
      if (keyPressed) {
        y1 = y1 - yspeed;
      }
    }
    if (y1 <=200) {
      y1 = 205;
    }
    if (y1 >= 931) {
      y1 = 931;
    }
  }
  void display() {
    image(imnorm2, x, y1);
  }
}

Projectile

public class Projectile {
  //GLOBAL VARIABLES
  boolean isRunning = false;
  float x;
  float y;
  float xspeed;
  PImage imnorm1;

  //CONSTRUCTOR
  Projectile(float _x, float _y) {
    x = _x;
    y = _y;
    imnorm1 = loadImage("playerprojectile.png");
  }
  //FUNCTIONS
  void run() {
    shot();
    display();
  }
  void display() {
    image(imnorm1, x, y);
  }
  void shot() {
    x += 10;
  }
}

background

public class Background {
  //GLOBAL VARIABLES

  //CONSTRUCTOR



  //FUNCTIONS
  void display() {
    background(0);
    strokeWeight(random(1, 5));
    int i = 0;
    while (i<1000) {
      float co = map(speed[i], 1, 5, 80, 255);
      stroke(co);
      strokeWeight(speed[i]);
      point(x[i], y[i]);

      x[i] = x[i] - speed[i];
      if (x[i] < 0) {
        x[i] = width;
      }
      i = i +1;
    }
  }
}

Answers

  • which line is the error on?

  • (we can't run the code because of all the missing music files and pngs)

  • Ah yes of course, sorry. It's line 222 of the main program

  • Here is a link to the file with everything (for helping purposes only) of course I trust people so. [http://expirebox.com/download/04dc9ed9049321547b8b0024578dd283.html]

  • edited March 2016

    The problem is that you are removing elements from the array list altering its size which affects the limits in the for loops.

    It is a common problem and you can find solutions on this forum. As a first step you might try try reversing the loops like this

    void collision() {
      for (int i = asteroid.size() - 1; i >=0; i--) {
        for (int j = shots.size() - 1; j >= 0; j--) {
          Projectile pj = (Projectile)shots.get(j);
          Asteroids at = (Asteroids)asteroid.get(i);
          if (pj.x < at.x - 16 && pj.y > at.y -16 && pj.y <= at.y + 16) {
            asteroid.remove(i);
            shots.remove(j);
            explosion.trigger();
            player.score += 1 ;
          }
        }
      }
    }
    
  • That actually causes a more immediate error, but thank you, I shalltry to look for an answer on here :)

  • edited March 2016

    A possible fix:

    void collision() {
      for (int i = shots.size(); i-- != 0; ) {
        final Projectile p = shots.get(i);
    
        for (int j = asteroid.size(); j-- != 0; ) {
          final Asteroids a = asteroid.get(j);
    
          if (p.x >= a.x & p.x < a.x+16 & & p.y >= a.y & p.y < a.y+16) {
            asteroid.remove(j);
            shots.remove(i);
    
            explosion.trigger();
            ++player.score;
    
            break;
          }
        }
      }
    }
    

    If you wish for a more performant collision check, take a look at function checkDeath() from this online example: http://studio.ProcessingTogether.com/sp/pad/export/ro.9K-kjhuONcJDZ

    For more forum threads about backwards loop + remove(), look it up here:
    https://forum.Processing.org/two/discussions/tagged/backwards

    P.S.: Read about how to declare the generic type <> below:
    https://Processing.org/reference/ArrayList.html

  • Yes my mistake should have been -- not ++ I have corrected it in my post

  • @Quark I tried this, however the problem still persists. As for what @GoToLoop said, it comes up with a type mismatch error "Java.lang.Object" does not match with "GameOfTheYear.Asteroids" which confuses me as I don't get why? Surely it IS an object so why would it not work?

  • edited March 2016

    Scratch that @GoToLoop - I fixed it :) Just gonna work on collision detection :)

  • Answer ✓

    Ahhh! Works perfectly now! just changed the 16 to 32! Haha, thank you all so much :))))

Sign In or Register to comment.