Alguém pode me explicar o que é esse erro? Por favor.
Parece que vc está tentando adicionar ou remover os elementos de uma coleção dentro da própria iteração. Pode postar o código do laço que vc está fazendo?
Evite postar imagens do erro. É melhor sempre que der, copiar e colar no post (pra mensagens de erro, para códigos tb, etc). E melhor se já fizer a formatação usando o botão do editor </>.
Este?
@Override
public void run() {
requestFocus();
long lastTime = System.nanoTime();
double amountOfticks = 60.0;
double ns = 1000000000 / amountOfticks;
double delta = 0;
int frames = 0;
double timer = System.currentTimeMillis();
while (isRunning) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if (delta >= 1) {
tick();
render();
frames++;
delta--;
if (System.currentTimeMillis() - timer >= 1000) {
System.out.println("FPS: " + frames);
frames = 0;
timer += 1000;
}
}
}
}
Posta a parte que tem a linha 92 da classe Game.
Eu tenho um arraylist entities que engloba todas as entidades do jogo.
Aqui eu chamo o tick das entidades, que basicamente compõe as animações ou interações da entidade.
public void tick() {
for (Entity entity : entities) {
entity.tick();
}
}
Será que em algum lugar (alguma dessas entidades que possuem o tick), não está modificando essa lista entities não?
Eu criei um método de colisão com uma lifepack, será que é isso?
public void checkCollisionLifePack() {
for(int i =0; i <Game.entities.size(); i++) {
Entity entity = Game.entities.get(i);
if (entity instanceof Lifepack) {
if(Entity.isColliding(this,entity)) {
life+=30;
if (life > maxLife) {
life = maxLife;
}
Game.entities.remove(entity);
}
}
}
}
Na classe Entity:
public static boolean isColliding(Entity e1, Entity e2) {
Rectangle boundsE1 = new Rectangle(e1.getX() + e1.maskx, e1.getY() + e1.masky,
e1.maskw, e1.maskh);
Rectangle boundsE2 = new Rectangle(e2.getX() + e2.maskx, e2.getY() + e2.masky,
e2.maskw, e2.maskh);
return boundsE1.intersects(boundsE2);
}
Se a chamada do tick no loop estiver chamando esse remove, há grandes chances de ser a causa do erro mesmo.
Faça um teste. coloque um breakpoint nesses removes e qdo parar nesse ponto, veja se o erro estoura logo em seguida.
Adicionei, mas não entendi direito o termo estoura ha ha.
hehe, foi mal. Estourar de “Estourar a exceção”. É quando o erro é lançado pelo sistema. No seu caso, é a exception: ConcurrentModificationException
.
Ahh, bem, ele estourou sim.
Uma forma de contornar esse erro é fazer o loop usando um iterator. Veja:
Iterator<Entity> iterator = entities.iterator();
while(iterator.hasNext()) {
Entity entity = iterator.next();
entity.tick();
}
Outra forma que talvez fique bom é marcar a Entity para ser removida e fazer a remoção logo após o for que executa o tick.
Pode me explicar melhor a segunda solução?
O que pensei foi. Em vez de vc remover a entity assim:
Game.entities.remove(entity);
Vc poderia marcar ela para remoção usando uma propriedade booleana:
entity.markToRemove(); // esse método iria simplesmente alterar uma propriedade de false pra true
E nessa parte, logo após o for, vc iria percorrer as entities e remover aquelas que foram marcadas.
public void tick() {
for (Entity entity : entities) {
entity.tick();
}
entities.removeIf(e -> e.isMarkedToRemove());
}
Mas confesso que não sei se é um bom caminho essa ideia, pq vc está desenvolvendo um jogo. Talvez tenha formas melhores de fazer isso nesse seu cenário.
Vou dar uma olhada, muito obrigado.
Apenas para informação, veja:
public class Main {
public static void main(String[] args) {
List<String> nomes = new ArrayList<>();
nomes.add("Aaa");
nomes.add("Bbb");
nomes.add("Ccc");
nomes.add("Ddd");
nomes.add("Eee");
// Estoura exceção
for (String n : nomes) {
if ("Ccc".equals(n)) {
nomes.remove(n);
}
}
// Não dá erro
// nomes.removeIf((n) -> "Ccc".equals(n));
// Não dá erro
// Iterator<String> iterator = nomes.iterator();
// while(iterator.hasNext()) {
// String n = iterator.next();
// if ("Ccc".equals(n)) {
// iterator.remove();
// }
// }
System.out.println(nomes);
}
}
Experimente rodar esse código testando cada parte (vá comentando e descomentando na medida que for executando). A que vc está fazendo é a primeira que estoura erro.
Nos meus games o método add e o remove populam uma lista de objetos a serem adicionados ao jogo e uma lista de objetos a serem removidos.
No método tick
, após o loop, eu adiciono na lista principal os elementos da lista de inserção e excluo da lista principal os elementos da lista de remoção.