Tengo un ArrayList de Minion objetos, y cuando un escudo choca con un esbirro, quiero quitar ese esbirro del ArrayList. Sin embargo, sólo puedo llegar a trabajar en 1, pero no de la otra manera. ¿alguien puede explicar plz ¿por qué?

En los 3 casos, estoy usando Android del procesador de onDrawFrame() método… así que no tengo control sobre el momento en que se llama. pero aquí está el código para todos 3 maneras:

Método 1: (no funciona)

public void onDrawFrame(GL10 gl) {
    List<Integer> indexesToRemove = new ArrayList<Integer>();
    int len = minions.size();
    for(int i=0; i<len; i++){
        if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds,  (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
            indexesToRemove.add(i);
        }
    }
    for(int i=indexesToRemove.size()-1; i>=0; i--){
        minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
    }
}

el problema es que la última línea minions.remove(indexesToRemove.get(i)); en REALIDAD no eliminar a los esbirros. NO se llama, con el propio índice. me he metido a través del depurador, corrió directamente hacia arriba, y el arraylist no se modifica en absoluto. ¿por qué es esto? en realidad, en el depurador, que la línea de «esbirros.quitar(indexesToRemove.get(i));» se llama un bijillion veces.

Método 2: (aún no funciona)

public void onDrawFrame(GL10 gl) {
    synchronized(minions){
        List<Integer> indexesToRemove = new ArrayList<Integer>();
        int len = minions.size();
        for(int i=0; i<len; i++){
            if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds,  (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
                indexesToRemove.add(i);
            }
        }
        for(int i=indexesToRemove.size()-1; i>=0; i--){
            minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
        }
    }
}

Aquí, pensé que… «oh, tal vez ya no es del todo sincronizado, el manuar a veces se llama también muchas veces y es el acceso al arraylist en el momento equivocado y tengo que bloquearlo. pero aún así no funciona. de nuevo, esa línea minions.remove(indexesToRemove.get(i)); se llama correctamente con el índice derecho, pero en realidad NO eliminar el objeto. estoy viendo a mi escudo en la pantalla slam de la derecha en el súbdito y no pasa nada a los súbditos (que no consigue quitarse de la arraylist)

Método #3 (esto funciona en realidad)

public void onDrawFrame(GL10 gl) {
    ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
    int len = colliders.size();
    for(int i=0; i<len; i++){
        GameObject collider = colliders.get(i);
        if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
            minions.remove(collider); //<---- why does THIS work instead?
        }
    }
}

este código funciona perfectamente. el escudo suena el súbdito y el súbdito cae muerto. como se puede ver aquí, la ÚNICA diferencia es que yo estoy utilizando la sobrecarga ArrayList.remove(object) lugar el método de extracción por índice. como en la línea de minions.remove(collider);. ¿por qué funciona ESTO ?

¿alguien puede por favor explicar?

en una nota de lado, aparte de almacenar otra variable de instancia, copia de la arraylist, ¿hay una mejor manera de administrar ArrayList<Minion> colliders = new ArrayList<Minion>(minions); ?

Nota: tanto el Escudo y Minion son regulares en Java los objetos que tienen una forma rectangular como límite. todos los que la matemática comprueba bien. lo he probado en el depurador y la detección de colisiones es exacta. Yo también soy de la actualización de los límites/posiciones precisas en el onDrawFrame() método.

InformationsquelleAutor David T. | 2013-01-22

3 Comentarios

  1. 10

    Porque ArrayList proporciona dos métodos que son:

    public E remove(int index)
    public boolean remove(Object o)

    Cuando se invoca minions.remove(indexesToRemove.get(i)), desde indexesToRemove es un List<Integer>, la invocación está obligado a la segunda firma en el que se quita un elemento especificando directamente el objeto, auto-unboxing no convertir su Integer en un int por lo que el elemento no se encuentra y no pasa nada.

    Tratar con: minions.remove((int)indexesToRemove.get(i)) para que la estática de la unión del método es aplicado correctamente.

    • mierda. buen ojo. no es de extrañar. gracias por la captura, y bien explicado.
  2. 7

    @Jack respuesta es correcta. Para la posteridad usted debe utilizar un Iterator aquí que usted puede quitar con dentro de su bucle:

    //synchronization wrapper here
    Iterator<Minion> iterator = minions.iterator();
    while (iterator.hasNext()) {
        Minion minion = iterator.next();
        if( OverlapTester.overlapCircleRectangle(..., minion.bounds)) {
            iterator.remove();
        }
    }
    • los otros chicos se explica el razonamiento. pero me gusta ur solucionar el mejor. estoy totalmente olvidó de los iteradores. gracias!!
  3. 3

    Es el tratamiento Entero como un objeto ref en el 1er dos ejemplo, la echó a un int

    • No hay necesidad de fundición, simplemente llame a Integer.intValue()

Dejar respuesta

Please enter your comment!
Please enter your name here