【问题标题】:Removing and adding actors to a group - libgdx删除和添加演员到组 - libgdx
【发布时间】:2020-06-17 11:50:47
【问题描述】:

我有一个组,它有一个将每个entity 与一个演员相关联的地图;它具有 addEntityremoveEntity 方法,用于在 Map 中添加和删除实体,以及在组中添加和删除实体。

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

这个组还有一个reset 方法,可以删除他所有的孩子并添加新的。

 public final void reset(final Collection<Entity> entities) {
    Gdx.app.postRunnable(() -> {
        removeEntities(entitesActors.keySet());
        this.addEntities(entities);
    });
}

第一次调用 reset (Map 和 group 为空)一切都很好,但第二次调用它(Map 和 Group 包含第一次调用的实体)我从 removeEntity 方法得到一个 cuncurrentModificationException。

我试着像这样编辑它:

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

或者绕过 removeEntities 方法直接调用:

this.clearChildren();
this.entitesActors.clear();

在这两种情况下都没有触发异常,演员被成功移除并添加到地图和组中,但他们没有被绘制到舞台上。 (每个actor中的方法draw被调用但我在屏幕上看不到它们,我得到的只是黑屏)。

有人知道正确的方法,或者可能告诉我我在哪里犯了错误?非常感谢您的帮助。

编辑:我尝试了@luis-fernando-frontanilla 解决方案,但没有成功。现在我的重置方法是这样的

public final void reset(final Collection<Entity> entities) {
    this.clearChildren();
    this.entitesActors.clear();
    this.addEntities(entities);
}

我尝试将整个重置方法包装在 Gdx.app.postRunnable 中

//EntityCrew is my Group object which has the reset method
Gdx.app.postRunnable(() -> this.entityCrew.reset(level.getEntities()));

而且我注意到,第一次使用这种设置时,我也看不到该组的演员。它们在组中,它们由渲染线程绘制但它们没有显示在屏幕上,这让我发疯。

【问题讨论】:

    标签: java libgdx


    【解决方案1】:

    第一次调用 reset (Map 和 group 为空)一切都很好,但第二次调用它(Map 和 Group 包含第一次调用的实体)我从 removeEntity 方法得到一个 cuncurrentModificationException。

    发生此异常的原因是,当您在 render() 方法中迭代集合时,该集合中的一个元素被删除,使迭代器不知道它应该做什么。

    对我们来说幸运的是,LibGDX 有一个 DelayedRemovalArray 类,它正是为这类情况而设计的。它的工作原理是这样的:

    • 告诉DelayedRemovalArray您要删除其中的一个或多个元素
    • 在要删除的元素上添加标志
    • 告诉DelayedRemovalArray您已完成设置标志
    • DelayedRemovalArray 等待迭代完成并删除标记的元素
    DelayedRemovalArray<Entity> array;
    // Prepare to flag elements
    array.begin();
    // Flag some elements
    array.removeIndex(index);
    // Finished flagging elements
    array.end();
    

    来自 LibGDX API:
    DelayedRemovalArray 是一个数组,它在迭代期间对移除进行排队,直到迭代完成。

    【讨论】:

    • 我将组的演员添加到数组中,然后按照您建议的方式删除所有演员,然后添加新的 EntityActor,但不幸的是我得到了相同的行为:/。我还编辑了我的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 2017-07-06
    相关资源
    最近更新 更多