I get "IndexOutOfBounds" in my Comets vs Spaceship Game - java

I began developing a "Spaceship vs Comets" style game last week and now I have come to a stop.
The purpose of the game is to shoot the comets before they pass your ship. You make the comets explode by firing at them. Simple idea!
However, sometimes when I play I get the "IndexOutOfBounds" error. It almost always appears when I haven't fired for a while (The size of my shots ArrayList is 0) and when I then fire and it collides it crashes.
So I have some kind of error in my code, but I really can't see it. I now hope that one of you might see why this accurs and save me from further "IndexOutOfBounds" errors! :)
Here is the part of the code that fails, including the functions that I use to move the comets and shots:
GAME CLASS
if(!Game.player.getShots().isEmpty() && !comet.getComets().isEmpty()) { //Om de är tomma så ignorera
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()) {
for(int y = 0; y < comet.getComets().size(); y++) { //Comets Y
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x)) && !comet.getComets().isEmpty() && !Game.player.getShots().isEmpty()) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
}
}
}
}
}
//Comet spawn timer
comet.addComets();
//Move the comets and shots!
Game.player.moveShots();
comet.moveComets();
repaint();
COMET CLASS
public ArrayList<Rectangle> getComets() {
return comets;
}
public void moveComets() {
if(!comets.isEmpty()) {
for(int x = 0; x < comets.size(); x++) {
comets.get(x).x -= cometSpeed;
}
}
}
PLAYER CLASS (Shots are in this class)
public void fire() {
shots.add(new Rectangle(x + player.width, y + 23, shotWidth,shotHeight));
}
public ArrayList<Rectangle> getShots() {
return shots;
}
public void moveShots() {
if(!shots.isEmpty()) {
for(int x = 0; x < shots.size(); x++) {
shots.get(x).x += fireSpeed;
}
}
}
Keep in mind that comets and shots are both "ArrayList out of the object Rectangle"
I will provide screenshots of error and a picture of the game below!
The error line is marked in the code above, the if statement should block it from crashing (I thought).
Thanks in advance! All help is appreciated! :)

You should change the order at the if statement to avoid it from evaluate one part of it.
You should change your condition to:
if( x < Game.player.getShots().size() && comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
That's because you're removing a shot and inside the comets for when the shoot is removed at the next comet iteration it will throw IndexOutOfBounds as the array no longer have the shot you're checking at the if, so you'll need to check again for the x existing on shots.
You can also do it at the for, you check for both conditions and you let the intersect as only check at the if.
A better performance if would be:
if(!Game.player.getShots().isEmpty() || !comet.getComets().isEmpty()) {
//if one of them is empty, won't be intersections
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
for(int y = 0; y < comet.getComets().size() && x < Game.player.getShots().size(); y++) {
//Comets Y only if the shoot still available
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
y = 0; // if you don't set the y = 0 the next shoot (as you removed the x, getShots.get(x) would be the x + 1 shoot) will only evaluate for the comets after y, won't evaluate the firsts comets at the array.
}
}
}
}

Try to adjust here if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()). You are checking for comet array twice.
Let me know if it works.

Is this code multithreaded?
I am also wondering why you are verifying comet.getComets().isEmpty() so many times.
My guess is that you are manipulating the ArrayList in some other part of your code. Reason I think this is because you are checking the size of the list multiple times and because within the for loop you are only deleting in the end, so that should not be the problem.
For instance if you run this method at two threads at the same time, the ArrayList can be checked at one point, but can reduce after checking the size. then when for instance the size was 10, but became 9, but you still try to delete x with value 10, you will get the out of bounds error.

Related

Skipping To The Next if Statement from Inside a for Loop

I've been learning some Java in my spare time and I'm a beginner, so I'm very sorry if I don't understand some simple concepts. I've been trying to make a "Robot" move around an already made map. I've been trying to make lines of a text file into multiple arrays (ie. moving forward, turning left, turning right). Then, I've been trying to use values in those arrays to make the robot move. Basically, if the text file says:
1 0 0
0 1 0
0 0 1
So the first line is for moving, the second is for turning left and the third is for turning left. This is supposed to make the robot move, and then not turn. Then it moves on to the next column and doesn't move, turns left, and doesn't turn right. I'm trying to make sure it works no matter how long the code is. I'm able to put it into three arrays correctly, but I'm having trouble with this for loop. When the loop executes and the values are all 1's or above, it works perfectly. However, if any value is a 0, it completely exits the loop and the robot doesn't move. Any help or advice would be appreciated! Thank you!
Code is below:
public static void robotMove(Robot x) throws Exception {
for (int i = 0; i < movedata.length; i++) {
int y = movedata[i];
int s = leftdata[i];
int j = rightdata[i];
for (int a = 0; a < movedata.length; a++) {
if (y == 0) {
//asking what to put here
}
else {
again.Move(x, y);
}
if (s == 0) {
//asking what to put here
}
else {
again.Left(x, s);
}
if (j == 0) {
//asking what to put here
}
else {
again.Right(x, j);
}
}
}
Assuming that movedata, leftdata and rightdata are the 3 arrays of same size corresponding to each line of your example, without knowing what again is but assuming it is the object handling the .Move(), .Left() and Right() actions made on the Robot x, I think the following should be enough:
public static void robotMove(Robot x) throws Exception {
for (int i = 0; i < movedata.length; i++) {
if (y != 0) {
again.Move(x, movedata[i]);
}
if (s != 0) {
again.Left(x, leftdata[i]);
}
if (j != 0) {
again.Right(x, rightdata[i]);
}
}
}
You can loop just once through movedata, I've removed the second nested loop.
If the value is 0, you do not want to do anything. Hence you don't need an else part for that, just put code in the if value != 0.
From a code perspesctive, it would be cleaner if instead of having some if taking care that the value is not 0, you may implement the "inaction" directly in the methods .Move(), .Left() and .Right().

IndexOutOfBoundsException appears when trying to delete an element from our arraylist

Currently, we are working on a shoot-em-up game. We have classes for both the bullets and the enemies. We have also created two arraylists where these elements can be found. Whenever a bullet hits an enemy, said enemy is supposed to simply disappear. Instead, we get this error.
void hit()
{
for(int i = 0; i < Bullet.size(); i++)
{
Bullet bul = (Bullet) Bullet.get(i);
Enemy enm = (Enemy)enemies.get(i);
if(bul.x < enm.x + enm.l && bul.x > enm.x - enm.l && enm.y<bul.y)
{
enm.health -= 1;
println("Pew");
if(enm.health <= 0)
{
enm = null;
enemies.remove(i);
}
}
}
}
A couple of things could be going wrong here. First, your for-loop goes through the Bullet ArrayList, however, you are using that index to modify the Enemy ArrayList as well. So if bul.size() > enm.size() "i.e. the bullet array is bigger than the enemy array", this would be what is causing the IndexOutOfBoundsException.
Additionally, if you are trying to check for an intersection of each bullet with each enemy you would want nested for-loops. Currently, you are just checking for if each bullet and enemy at the same index are intersecting.
You could resolve this with the following:
for(int i = 0; i < bul.size(); i++){
for(int j = 0; j < enm.size(); j++){
//if bullet is intersecting enemy
//do something
}
}

Counting the amount of a specific object in 2D Array Java

In a checkers game for my CS class I have run into trouble with counting how many of a specific color piece are on the board.
Here is the getter method:
public int getCheckersBlue()
{
int counter = 0;
for(int x = 0; x <= 8; x++)
{
for(int y = 0; y <= 12; y++)
{
if(c[x][y].equals(Color.BLUE))
{
counter++;
}
}
}
return counter;
}
The constructor for c:
private CheckersBoard[][] c = new CheckersBoard[8][8];
Whenever trying to run the game in Greenfoot a null pointer exception is thrown even when the code compiles. Even with everything declared, everything has something it's pointing to. Any suggestions?
I see two major problems in your code:
You're iterating over 0-8 elements for x and 0-12 for y, but in declaration you has 0-7 for x and the same for y
NullPointerException. This caused because array declaration will fill your array with null values, so you're comparing null with Color.Blue which is incorrect.
With the both fixes code will look like this
public int getCheckersBlue()
{
int counter = 0;
for(int x = 0; x < 8; x++)
{
for(int y = 0; y < 8; y++)
{
if(Color.BLUE.equals(c[x][y]))
{
counter++;
}
}
}
return counter;
}
But I think it's still logically incorrect.
Okay, a few of things...
You are iterating through 12 every time in the inner loop when it should be 8.
Color.Blue is a JavaFX Paint, I believe. This is not really what you should be using. Unless you have made your own Enumeration type of Color, you should do so. Here is a link for how to do so with relevant examples.
You are checking equality of two different types: CheckersBoard and Color. You should have a CheckersBoard.getSpace(x, y).getColor() or CheckersBoard.getSpace(x, y).getOccupancy() (which should have a NoOccupancy option) if we want to be completely logistically sound with our naming.

Java game check if shoot fire touched monster is too slow

I've made a simple game, where you are the box and you are shooting little boxes.
Now to check if the shoot tocuhed the monster, i check if its x is highter or equals to the monster's x, and then i check if its less or equals to the monsters x, and then the same for y.
But the thing is, I have two for loops for this, therefore when I shoot and it touched the monster, the monster will not always get deleted cause the for loop did not reach that monster yet, and im sure it's bad for performance.
IS there a faster way to do this? why is it happening?
private void checkKilled() {
for (int i = 0; i < this.shoots.size(); i++) {
for (int j = 0; j < this.monsters.size(); j++) {
Monster m = this.monsters.get(j);
Shoot s = this.shoots.get(i);
if (s.getX() >= m.getX() && s.getX() <= m.getX() + 15
&& s.getY() >= m.getY() && s.getY() <= m.getY() + 15) {
m.isDead = true;
s.isExploded = true;
}
}
}
}
Not fully understanding the problem, but for performance you can break from inner loop if condition is true; it will then go to next shoot.
...
s.isExploded = true;
break;
}

What is wrong with this circle-to-circle collision?

I have a simple java application that tests for collision off 4 walls and off each of the 10 balls... I have the walls figured out but circle-to-circle doesn't seem to work for me. When I run this segment along with the rest of the program I get 10 very shaky circles (that appear to be colliding with themselves) and they don't move very much at all. If I take this segment out I get 10 circles that move smoothly and collide off of the 4 walls. Can someone tell me what might be causing the problem? THANKS
for (int j = 0; j < ballnum; ++j) {
for (int k = 0; k < ballnum; ++k) {
if (Math.sqrt((Math.pow(balls[j].givebackpoint().x - balls[k].givebackpoint().x, 2))
+ (Math.sqrt(Math.pow(balls[j].givebackpoint().y - balls[k].givebackpoint().y, 2)))) <= 2 * RADIUS) {
if (balls[j].givebackangle() >= 180) {
balls[j].setangle(balls[j].givebackangle()-180);
}
else{
balls[j].setangle(360-balls[j].givebackangle());
}
}
}
}
You're checking each ball against itself.
You need to skip running the tests when j == k with a line like this at the top of your inner for loop:
if (j == k)
continue;
Unless I'm missing it, you don't seem to be skipping where j == k. So you are right that they are colliding with themselves.

Categories