1
votes

J'obtiens "IndexOutOfBounds" dans mon jeu Comets vs Spaceship

J'ai commencé à développer un jeu de style "Vaisseau Spatial vs Comètes" la semaine dernière et maintenant je suis arrêté.

Le but du jeu est de tirer sur les comètes avant qu'elles ne passent devant votre vaisseau. Vous faites exploser les comètes en leur tirant dessus. Idée simple!

Cependant, parfois, lorsque je joue, j'obtiens l'erreur "IndexOutOfBounds" . Il apparaît presque toujours lorsque je n'ai pas tiré depuis un moment (la taille de mes coups ArrayList est de 0) et quand je tire et qu'il entre en collision, il plante.

Donc je J'ai une sorte d'erreur dans mon code, mais je ne peux vraiment pas le voir. J'espère maintenant que l'un de vous comprendra pourquoi cela maudit et me sauvera d'autres erreurs "IndexOutOfBounds"! :)

Voici la partie du code qui échoue, y compris les fonctions que j'utilise pour déplacer les comètes et les plans:

CLASSE DE JEU p>

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;
        }
    }
}

CLASSE COMÈTE

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;
        }
    }

}

CLASSE DE JOUEUR (Les coups sont dans cette classe)

    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();

Gardez à l'esprit que les comètes et les plans sont tous deux "ArrayList hors de l'objet Rectangle"

Je vais fournir des captures d'écran d'erreur et une image du jeu ci-dessous!

Image de l'interface graphique

Photo de l'erreur dans la console

La ligne d'erreur est marquée dans le code ci-dessus, l'instruction if devrait l'empêcher de planter (j'ai pensé).

Merci d'avance ! Toute aide est appréciée! :)


5 commentaires

Vérifiez la ligne 128 de votre classe de jeu, c'est là que ça se passe. déboguez votre code et voyez ce qui ne va pas.


J'ai déjà fait ça, je n'arrive pas à comprendre ... Je vérifie si elles sont vides ou non sur cette ligne donc ça ne devrait pas pouvoir passer


les instructions Bool au if sont généralement évaluées de gauche à droite, vous devez vérifier si elles sont vides à gauche de l'intersection


Je vais essayer ça @BrunoLoops merci!


Heya mate, une suggestion pour aider à l'organisation du code ... vous voudrez peut-être que tous vos objets à l'écran qui se déplacent / se heurtent héritent d'une interface GameObject qui a une update () < / code> méthode qui doit être implémentée. Ensuite, vous pouvez vous-même contenir dans chaque objet sa propre mise à jour de mouvement et vérification de collision. À partir de là, dans votre boucle principale de jeu, il vous suffit de parcourir toutes vos sous-classes GameObject et d'appeler la méthode update () . Pourrait vous aider avec le débogage et la réduction des boucles imbriquées comme dans votre classe Game .


3 Réponses :


2
votes

Essayez de régler ici if (! comet.getComets (). isEmpty () &&! comet.getComets (). isEmpty ()) . Vous vérifiez deux fois le tableau des comètes.

Faites-moi savoir si cela fonctionne.


1 commentaires

J'ai résolu le problème, cela n'a pas fonctionné! Merci quand même de l'avoir signalé!



2
votes

Vous devez changer l'ordre de l'instruction if pour éviter qu'elle n'en évalue une partie. Vous devez changer votre condition en:

if (x

C'est parce que vous supprimez un plan et à l'intérieur des comètes, lorsque le tir est supprimé à la prochaine itération de comète, il lancera IndexOutOfBounds code> car le tableau n'a plus le plan que vous vérifiez au if, vous devrez donc vérifier à nouveau le x existant sur les plans. Vous pouvez également le faire au for, vous vérifiez les deux conditions et vous laissez l'intersection comme seulement vérifier au if.

Une meilleure performance si serait:

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.
                    }

                }
            }

        }


1 commentaires

Oui, cela l'a corrigé! Je n'y ai pas pensé. Je prendrai un stylo et du papier la prochaine fois et le déboguerai de cette façon lorsque je ferai face à ce problème une autre fois! Merci @BrunoLoops



1
votes

Ce code est-il multithread? Je me demande aussi pourquoi vous vérifiez si souvent comet.getComets (). IsEmpty () .

Je suppose que vous manipulez la ArrayList dans une autre partie de votre code. Raison pour laquelle je pense que c'est parce que vous vérifiez la taille de la liste plusieurs fois et parce que dans la boucle for, vous ne supprimez qu'à la fin, donc cela ne devrait pas être le problème.

Par exemple, si vous exécutez cette méthode sur deux threads en même temps, l'ArrayList peut être vérifié à un moment donné, mais peut être réduit après avoir vérifié la taille. alors quand, par exemple, la taille était 10, mais est devenue 9, mais que vous essayez toujours de supprimer x avec la valeur 10, vous obtiendrez l'erreur hors limites.


1 commentaires

Je pense qu'il utilise 1 fil, je ne sais pas comment vérifier. Je vérifie si elle est vide autant de fois parce que je pensais qu'il y avait un espace quelque part. Je peux supprimer certaines de ces déclarations if si je le souhaite. Le problème était ce que BrunoLoops a dit plus tôt