We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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]
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
That actually causes a more immediate error, but thank you, I shalltry to look for an answer on here :)
A possible fix:
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?
Scratch that @GoToLoop - I fixed it :) Just gonna work on collision detection :)
Ahhh! Works perfectly now! just changed the 16 to 32! Haha, thank you all so much :))))