Reputation: 69
I have a group that has a Map that associates every entity
with an actor; it has the method addEntity
and removeEntity
for adding and deleting entities to/from the Map and their respective actors to/from the group.
public final void addEntity(final Entity entity) {
EntityActor entityActor = new EntityActor(entity, shapeRenderer);
this.addActor(entityActor); //adding the actor to the group
this.entitesActors.put(entity, entityActor); //adding the actor to the map
}
public final void addEntities(final Collection<Entity> entities) {
entities.stream().forEach(this::addEntity);
}
public final void removeEntity(final Entity entity) {
entitesActors.get(entity).addAction(Actions.removeActor()); //removes actor from group
this.entitesActors.remove(entity); //removes actor from map
}
public final void removeEntities(final Collection<Entity> entities) {
entities.forEach(this::removeEntity);
}
This group also has a reset
method that deletes all his children and adds new ones.
public final void reset(final Collection<Entity> entities) {
Gdx.app.postRunnable(() -> {
removeEntities(entitesActors.keySet());
this.addEntities(entities);
});
}
The first time reset is called (Map and group are empty) everything's fine, but the second time I call it (with Map and Group containing the entities of the first call) I got a cuncurrentModificationException from the removeEntity method.
I tried to edit it like this:
public final void removeEntities(final Collection<Entity> entities) {
entitesActors.entrySet().stream().filter(e -> entities.contains(e.getKey())).map(e -> e.getValue())
.forEach(a -> a.addAction(Actions.removeActor()));
entitesActors.keySet().removeAll(entities);
}
Or bypassing removeEntities method and just calling:
this.clearChildren();
this.entitesActors.clear();
In both cases no exception is fired, the actors are successfully removed and added in both Map and Group but they are not drawn onto the stage. (the method draw in each actor is called but I can't see them on screen, all I got is a black screen).
Somebody know the correct way to do it or maybe telling me where I make a mistake? Thanks very much for the help.
EDIT: I tried @luis-fernando-frontanilla solution but it didn't worked out. Now my reset method looks like this
public final void reset(final Collection<Entity> entities) {
this.clearChildren();
this.entitesActors.clear();
this.addEntities(entities);
}
And I tried to wrap the whole reset method inside a Gdx.app.postRunnable
//EntityCrew is my Group object which has the reset method
Gdx.app.postRunnable(() -> this.entityCrew.reset(level.getEntities()));
And I noticed that with this setup the first time too I can't see the actors of the group. They are in the group, they are drawn by the render thread but they are not displayed on screen and this thing is driving me mad.
Upvotes: 0
Views: 619
Reputation: 1160
The first time reset is called (Map and group are empty) everything's fine, but the second time I call it (with Map and Group containing the entities of the first call) I got a cuncurrentModificationException from the removeEntity method.
This exception happens because when you're iterating through the Collection in the render()
method one element in that collection is removed confusing the iterator on what it should do.
Luckily for us, LibGDX has a DelayedRemovalArray
class that is made exactly for these kind of cases. It works like this:
DelayedRemovalArray
you want to delete one or many of its elementsDelayedRemovalArray
you finished setting the flagsDelayedRemovalArray
waits for the iteration to finish and deletes the flagged elementsDelayedRemovalArray<Entity> array;
// Prepare to flag elements
array.begin();
// Flag some elements
array.removeIndex(index);
// Finished flagging elements
array.end();
From the LibGDX API:
DelayedRemovalArray is an array that queues removal during iteration until the iteration has completed.
Upvotes: 1